From 2639796255d820d720e086e905e19226af2cbd4d Mon Sep 17 00:00:00 2001 From: jamesbrq Date: Sun, 9 Mar 2025 11:37:15 -0400 Subject: [PATCH] MLSS: Add new goal + Update basepatch to standalone equivalent (#4409) * Item groups + small changes * Add alternate goal * New Locations and Logic Updates + Basepatch * Update basepatch.bsdiff * Update Basepatch * Update basepatch.bsdiff * Update bowsers castle logic with emblem hunt * Update Archipelago Unittests.run.xml * Update Archipelago Unittests.run.xml * Fix for overlapping ROM addresses * Update Rom.py * Update __init__.py * Update basepatch.bsdiff * Update Rom.py * Update client with new helper function * Update basepatch.bsdiff * Update worlds/mlss/__init__.py Co-authored-by: qwint * Update worlds/mlss/__init__.py Co-authored-by: qwint * Review Refactor * Review Refactor --------- Co-authored-by: qwint --- worlds/mlss/Client.py | 2 +- worlds/mlss/Data.py | 2 +- worlds/mlss/Items.py | 8 +++ worlds/mlss/Locations.py | 16 +++-- worlds/mlss/Names/LocationName.py | 8 +-- worlds/mlss/Options.py | 45 ++++++++++-- worlds/mlss/Regions.py | 24 +++++-- worlds/mlss/Rom.py | 16 +++-- worlds/mlss/Rules.py | 116 ++++++++++++++++++++++++++++-- worlds/mlss/StateLogic.py | 23 +++++- worlds/mlss/__init__.py | 13 +++- worlds/mlss/data/basepatch.bsdiff | Bin 18482 -> 21812 bytes 12 files changed, 234 insertions(+), 39 deletions(-) diff --git a/worlds/mlss/Client.py b/worlds/mlss/Client.py index 75f6ac65..17d87197 100644 --- a/worlds/mlss/Client.py +++ b/worlds/mlss/Client.py @@ -269,7 +269,7 @@ class MLSSClient(BizHawkClient): self.local_checked_locations = locs_to_send if locs_to_send is not None: - await ctx.send_msgs([{"cmd": "LocationChecks", "locations": list(locs_to_send)}]) + await ctx.check_locations(locs_to_send) except bizhawk.RequestFailedError: # Exit handler and return to main loop to reconnect. diff --git a/worlds/mlss/Data.py b/worlds/mlss/Data.py index add14aa0..7e3605f1 100644 --- a/worlds/mlss/Data.py +++ b/worlds/mlss/Data.py @@ -153,7 +153,6 @@ enemies = [ 0x50458C, 0x5045AC, 0x50468C, - # 0x5046CC, 6 enemy formation 0x5046EC, 0x50470C ] @@ -166,6 +165,7 @@ bosses = [ 0x50360C, 0x5037AC, 0x5037CC, + 0x50396C, 0x503A8C, 0x503D6C, 0x503F0C, diff --git a/worlds/mlss/Items.py b/worlds/mlss/Items.py index 717443dd..5fca829b 100644 --- a/worlds/mlss/Items.py +++ b/worlds/mlss/Items.py @@ -160,6 +160,7 @@ itemList: typing.List[ItemData] = [ ItemData(77771142, "Game Boy Horror SP", ItemClassification.useful, 0xFE), ItemData(77771143, "Woo Bean", ItemClassification.skip_balancing, 0x1C), ItemData(77771144, "Hee Bean", ItemClassification.skip_balancing, 0x1F), + ItemData(77771145, "Beanstar Emblem", ItemClassification.progression, 0x3E), ] item_frequencies: typing.Dict[str, int] = { @@ -186,5 +187,12 @@ item_frequencies: typing.Dict[str, int] = { "Hammers": 3, } +mlss_item_name_groups = { + "Beanstar Piece": { "Beanstar Piece 1", "Beanstar Piece 2", "Beanstar Piece 3", "Beanstar Piece 4"}, + "Beanfruit": { "Bean Fruit 1", "Bean Fruit 2", "Bean Fruit 3", "Bean Fruit 4", "Bean Fruit 5", "Bean Fruit 6", "Bean Fruit 7"}, + "Neon Egg": { "Blue Neon Egg", "Red Neon Egg", "Green Neon Egg", "Yellow Neon Egg", "Purple Neon Egg", "Orange Neon Egg", "Azure Neon Egg"}, + "Chuckola Fruit": { "Red Chuckola Fruit", "Purple Chuckola Fruit", "White Chuckola Fruit"} +} + item_table: typing.Dict[str, ItemData] = {item.itemName: item for item in itemList} items_by_id: typing.Dict[int, ItemData] = {item.code: item for item in itemList} diff --git a/worlds/mlss/Locations.py b/worlds/mlss/Locations.py index a2787ef9..9a114bc4 100644 --- a/worlds/mlss/Locations.py +++ b/worlds/mlss/Locations.py @@ -251,9 +251,9 @@ coins: typing.List[LocationData] = [ LocationData("Hoohoo Village North Cave Room 1 Coin Block", 0x39DAA0, 0), LocationData("Hoohoo Village South Cave Coin Block 1", 0x39DAC5, 0), LocationData("Hoohoo Village South Cave Coin Block 2", 0x39DAD5, 0), - LocationData("Hoohoo Mountain Base Boo Statue Cave Coin Block 1", 0x39DAE2, 0), - LocationData("Hoohoo Mountain Base Boo Statue Cave Coin Block 2", 0x39DAF2, 0), - LocationData("Hoohoo Mountain Base Boo Statue Cave Coin Block 3", 0x39DAFA, 0), + LocationData("Hoohoo Mountain Base Boostatue Cave Coin Block 1", 0x39DAE2, 0), + LocationData("Hoohoo Mountain Base Boostatue Cave Coin Block 2", 0x39DAF2, 0), + LocationData("Hoohoo Mountain Base Boostatue Cave Coin Block 3", 0x39DAFA, 0), LocationData("Beanbean Outskirts NW Coin Block", 0x39DB8F, 0), LocationData("Beanbean Outskirts S Room 1 Coin Block", 0x39DC18, 0), LocationData("Beanbean Outskirts S Room 2 Coin Block", 0x39DC3D, 0), @@ -262,6 +262,8 @@ coins: typing.List[LocationData] = [ LocationData("Chucklehuck Woods Cave Room 1 Coin Block", 0x39DD7A, 0), LocationData("Chucklehuck Woods Cave Room 2 Coin Block", 0x39DD97, 0), LocationData("Chucklehuck Woods Cave Room 3 Coin Block", 0x39DDB4, 0), + LocationData("Chucklehuck Woods Solo Luigi Cave Room 1 Coin Block 1", 0x39DB48, 0), + LocationData("Chucklehuck Woods Solo Luigi Cave Room 1 Coin Block 2", 0x39DB50, 0), LocationData("Chucklehuck Woods Pipe 5 Room Coin Block", 0x39DDE6, 0), LocationData("Chucklehuck Woods Room 7 Coin Block", 0x39DE31, 0), LocationData("Chucklehuck Woods Past Chuckleroot Coin Block", 0x39DF14, 0), @@ -289,6 +291,7 @@ baseUltraRocks: typing.List[LocationData] = [ LocationData("Teehee Valley Upper Maze Room 1 Block", 0x39E5E0, 0), LocationData("Teehee Valley Upper Maze Room 2 Digspot 1", 0x39E5C8, 0), LocationData("Teehee Valley Upper Maze Room 2 Digspot 2", 0x39E5D0, 0), + LocationData("Guffawha Ruins Block", 0x39E6A3, 0), LocationData("Hoohoo Mountain Base Guffawha Ruins Entrance Digspot", 0x39DA0B, 0), LocationData("Hoohoo Mountain Base Teehee Valley Entrance Digspot", 0x39DA20, 0), LocationData("Hoohoo Mountain Base Teehee Valley Entrance Block", 0x39DA18, 0), @@ -298,7 +301,7 @@ booStatue: typing.List[LocationData] = [ LocationData("Beanbean Outskirts Before Harhall Digspot 1", 0x39E951, 0), LocationData("Beanbean Outskirts Before Harhall Digspot 2", 0x39E959, 0), LocationData("Beanstar Piece Harhall", 0x1E9441, 2), - LocationData("Beanbean Outskirts Boo Statue Mole", 0x1E9434, 2), + LocationData("Beanbean Outskirts Boostatue Mole", 0x1E9434, 2), LocationData("Harhall's Pants", 0x1E9444, 2), LocationData("Beanbean Outskirts S Room 2 Digspot 1", 0x39DC65, 0), LocationData("Beanbean Outskirts S Room 2 Digspot 2", 0x39DC5D, 0), @@ -317,6 +320,9 @@ chucklehuck: typing.List[LocationData] = [ LocationData("Chucklehuck Woods Cave Room 1 Block 2", 0x39DD8A, 0), LocationData("Chucklehuck Woods Cave Room 2 Block", 0x39DD9F, 0), LocationData("Chucklehuck Woods Cave Room 3 Block", 0x39DDAC, 0), + LocationData("Chucklehuck Woods Solo Luigi Cave Room 2 Block", 0x39DB72, 0), + LocationData("Chucklehuck Woods Solo Luigi Cave Room 3 Block 1", 0x39DB5D, 0), + LocationData("Chucklehuck Woods Solo Luigi Cave Room 3 Block 2", 0x39DB65, 0), LocationData("Chucklehuck Woods Room 2 Block", 0x39DDC1, 0), LocationData("Chucklehuck Woods Room 2 Digspot", 0x39DDC9, 0), LocationData("Chucklehuck Woods Pipe Room Block 1", 0x39DDD6, 0), @@ -786,7 +792,7 @@ nonBlock = [ (0x4373, 0x10, 0x277A45), # Teehee Valley Mole (0x434D, 0x8, 0x1E9444), # Harhall's Pants (0x432E, 0x10, 0x1E9441), # Harhall Beanstar Piece - (0x434B, 0x8, 0x1E9434), # Outskirts Boo Statue Mole + (0x434B, 0x8, 0x1E9434), # Outskirts Boostatue Mole (0x42FE, 0x2, 0x1E943E), # Red Goblet (0x42FE, 0x4, 0x24E628), # Green Goblet (0x4301, 0x10, 0x250621), # Red Chuckola Fruit diff --git a/worlds/mlss/Names/LocationName.py b/worlds/mlss/Names/LocationName.py index 5b38b2a1..43b75bf5 100644 --- a/worlds/mlss/Names/LocationName.py +++ b/worlds/mlss/Names/LocationName.py @@ -59,7 +59,7 @@ class LocationName: HoohooMountainBaseBoostatueRoomDigspot1 = "Hoohoo Mountain Base Boostatue Room Digspot 1" HoohooMountainBaseBoostatueRoomDigspot2 = "Hoohoo Mountain Base Boostatue Room Digspot 2" HoohooMountainBaseBoostatueRoomDigspot3 = "Hoohoo Mountain Base Boostatue Room Digspot 3" - BeanbeanOutskirtsBooStatueMole = "Beanbean Outskirts Boo Statue Mole" + BeanbeanOutskirtsBooStatueMole = "Beanbean Outskirts Boostatue Mole" HoohooMountainBaseGrassyAreaBlock1 = "Hoohoo Mountain Base Grassy Area Block 1" HoohooMountainBaseGrassyAreaBlock2 = "Hoohoo Mountain Base Grassy Area Block 2" HoohooMountainBaseGuffawhaRuinsEntranceDigspot = "Hoohoo Mountain Base Guffawha Ruins Entrance Digspot" @@ -533,9 +533,9 @@ class LocationName: BadgeShopMomPiranhaFlag2 = "Badge Shop Mom Piranha Flag 2" BadgeShopMomPiranhaFlag3 = "Badge Shop Mom Piranha Flag 3" HarhallsPants = "Harhall's Pants" - HoohooMountainBaseBooStatueCaveCoinBlock1 = "Hoohoo Mountain Base Boo Statue Cave Coin Block 1" - HoohooMountainBaseBooStatueCaveCoinBlock2 = "Hoohoo Mountain Base Boo Statue Cave Coin Block 2" - HoohooMountainBaseBooStatueCaveCoinBlock3 = "Hoohoo Mountain Base Boo Statue Cave Coin Block 3" + HoohooMountainBaseBooStatueCaveCoinBlock1 = "Hoohoo Mountain Base Boostatue Cave Coin Block 1" + HoohooMountainBaseBooStatueCaveCoinBlock2 = "Hoohoo Mountain Base Boostatue Cave Coin Block 2" + HoohooMountainBaseBooStatueCaveCoinBlock3 = "Hoohoo Mountain Base Boostatue Cave Coin Block 3" BeanbeanOutskirtsNWCoinBlock = "Beanbean Outskirts NW Coin Block" BeanbeanOutskirtsSRoom1CoinBlock = "Beanbean Outskirts S Room 1 Coin Block" BeanbeanOutskirtsSRoom2CoinBlock = "Beanbean Outskirts S Room 2 Coin Block" diff --git a/worlds/mlss/Options.py b/worlds/mlss/Options.py index 73e8ebd4..dbf581b2 100644 --- a/worlds/mlss/Options.py +++ b/worlds/mlss/Options.py @@ -2,13 +2,13 @@ from Options import Choice, Toggle, StartInventoryPool, PerGameCommonOptions, Ra from dataclasses import dataclass -class BowsersCastleSkip(Toggle): +class SkipBowsersCastle(Toggle): """ - Skip straight from the entrance hall to Bowletta in Bowser's Castle. + Skip straight from the Entrance Hall to Bowletta in Bowser's Castle. All Bowser's Castle locations will be removed from the location pool. """ - display_name = "Bowser's Castle Skip" + display_name = "Skip Bowser's Castle" class ExtraPipes(Toggle): @@ -272,13 +272,47 @@ class ChuckleBeans(Choice): option_all = 2 default = 2 +class Goal(Choice): + """ + Vanilla: Complete jokes end with the required items and defeat Birdo to unlock Bowser's Castle. + + Emblem Hunt: Find the required number of Beanstar Emblems to gain access to Bowser's Castle. + """ + display_name = "Goal" + option_vanilla = 0 + option_emblem_hunt = 1 + default = 0 + +class EmblemsRequired(Range): + """ + Number of Beanstar Emblems to collect to unlock Bowser's Castle. + + If Goal is not Emblem Hunt, this does nothing. + """ + display_name = "Emblems Required" + range_start = 1 + range_end = 100 + default = 50 + + +class EmblemsAmount(Range): + """ + Number of Beanstar Emblems that are in the pool. + + If Goal is not Emblem Hunt, this does nothing. + """ + display_name = "Emblems Available" + range_start = 1 + range_end = 150 + default = 75 + @dataclass class MLSSOptions(PerGameCommonOptions): start_inventory_from_pool: StartInventoryPool coins: Coins difficult_logic: DifficultLogic - castle_skip: BowsersCastleSkip + castle_skip: SkipBowsersCastle extra_pipes: ExtraPipes skip_minecart: SkipMinecart disable_surf: DisableSurf @@ -286,6 +320,9 @@ class MLSSOptions(PerGameCommonOptions): harhalls_pants: Removed block_visibility: HiddenVisible chuckle_beans: ChuckleBeans + goal: Goal + emblems_required: EmblemsRequired + emblems_amount: EmblemsAmount music_options: MusicOptions randomize_sounds: RandomSounds randomize_enemies: RandomizeEnemies diff --git a/worlds/mlss/Regions.py b/worlds/mlss/Regions.py index 7dd5e945..e9008b86 100644 --- a/worlds/mlss/Regions.py +++ b/worlds/mlss/Regions.py @@ -91,6 +91,16 @@ def connect_regions(world: "MLSSWorld"): connect(world, names, "Main Area", "BaseUltraRocks", lambda state: StateLogic.ultra(state, world.player)) connect(world, names, "Main Area", "Chucklehuck Woods", lambda state: StateLogic.brooch(state, world.player)) connect(world, names, "Main Area", "BooStatue", lambda state: StateLogic.canCrash(state, world.player)) + if world.options.goal == "emblem_hunt": + if world.options.castle_skip: + connect(world, names, "Main Area", "Cackletta's Soul", + lambda state: state.has("Beanstar Emblem", world.player, world.options.emblems_required.value)) + else: + connect(world, names, "Main Area", "Bowser's Castle", lambda state: state.has("Beanstar Emblem", world.player, world.options.emblems_required.value)) + connect(world, names, "Bowser's Castle", "Bowser's Castle Mini", lambda state: + StateLogic.canMini(state, world.player) + and StateLogic.thunder(state,world.player)) + connect(world, names, "Bowser's Castle Mini", "Cackletta's Soul", lambda state: StateLogic.soul(state, world.player)) connect( world, names, @@ -213,8 +223,8 @@ def connect_regions(world: "MLSSWorld"): connect(world, names, "Surfable", "GwarharEntrance") connect(world, names, "Surfable", "Oasis") connect(world, names, "Surfable", "JokesEntrance", lambda state: StateLogic.fire(state, world.player)) - connect(world, names, "JokesMain", "PostJokes", lambda state: StateLogic.postJokes(state, world.player)) - if not world.options.castle_skip: + connect(world, names, "JokesMain", "PostJokes", lambda state: StateLogic.postJokes(state, world.player, world.options.goal.value)) + if not world.options.castle_skip and world.options.goal != "emblem_hunt": connect(world, names, "PostJokes", "Bowser's Castle") connect( world, @@ -224,7 +234,7 @@ def connect_regions(world: "MLSSWorld"): lambda state: StateLogic.canMini(state, world.player) and StateLogic.thunder(state, world.player), ) connect(world, names, "Bowser's Castle Mini", "Cackletta's Soul") - else: + elif world.options.goal != "emblem_hunt": connect(world, names, "PostJokes", "Cackletta's Soul") connect(world, names, "Chucklehuck Woods", "Winkle", lambda state: StateLogic.canDash(state, world.player)) connect( @@ -247,14 +257,14 @@ def connect_regions(world: "MLSSWorld"): names, "Shop Starting Flag", "Shop Birdo Flag", - lambda state: StateLogic.postJokes(state, world.player), + lambda state: StateLogic.postJokes(state, world.player, world.options.goal.value), ) connect( world, names, "Fungitown", "Fungitown Shop Birdo Flag", - lambda state: StateLogic.postJokes(state, world.player), + lambda state: StateLogic.postJokes(state, world.player, world.options.goal.value), ) else: connect( @@ -276,14 +286,14 @@ def connect_regions(world: "MLSSWorld"): names, "Shop Starting Flag", "Shop Birdo Flag", - lambda state: StateLogic.canCrash(state, world.player) and StateLogic.postJokes(state, world.player), + lambda state: StateLogic.canCrash(state, world.player) and StateLogic.postJokes(state, world.player, world.options.goal.value), ) connect( world, names, "Fungitown", "Fungitown Shop Birdo Flag", - lambda state: StateLogic.canCrash(state, world.player) and StateLogic.postJokes(state, world.player), + lambda state: StateLogic.canCrash(state, world.player) and StateLogic.postJokes(state, world.player, world.options.goal.value), ) diff --git a/worlds/mlss/Rom.py b/worlds/mlss/Rom.py index 03eac040..c83c0121 100644 --- a/worlds/mlss/Rom.py +++ b/worlds/mlss/Rom.py @@ -177,10 +177,10 @@ class MLSSPatchExtension(APPatchExtension): for pos in enemies: stream.seek(pos + 8) for _ in range(6): - enemy = int.from_bytes(stream.read(1)) + enemy = int.from_bytes(stream.read(1), "little") if enemy > 0: stream.seek(1, 1) - flag = int.from_bytes(stream.read(1)) + flag = int.from_bytes(stream.read(1), "little") if flag == 0x7: break if flag in [0x0, 0x2, 0x4]: @@ -196,12 +196,12 @@ class MLSSPatchExtension(APPatchExtension): stream.seek(pos + 8) for _ in range(6): - enemy = int.from_bytes(stream.read(1)) + enemy = int.from_bytes(stream.read(1), "little") if enemy > 0 and enemy not in Data.flying and enemy not in Data.pestnut: if enemy == 0x52: chomp = True stream.seek(1, 1) - flag = int.from_bytes(stream.read(1)) + flag = int.from_bytes(stream.read(1), "little") if flag not in [0x0, 0x2, 0x4]: stream.seek(1, 1) continue @@ -234,7 +234,7 @@ class MLSSPatchExtension(APPatchExtension): stream.seek(pos) temp = stream.read(1) stream.seek(pos) - stream.write(bytes([temp[0] | 0x8])) + stream.write(bytes([temp[0] | 0x80])) stream.seek(pos + 1) stream.write(groups.pop()) @@ -316,6 +316,10 @@ def write_tokens(world: "MLSSWorld", patch: MLSSProcedurePatch) -> None: patch.write_token(APTokenTypes.WRITE, 0xD00003, bytes([world.options.xp_multiplier.value])) + if world.options.goal == 1: + patch.write_token(APTokenTypes.WRITE, 0xD00008, bytes([world.options.goal.value])) + patch.write_token(APTokenTypes.WRITE, 0xD00009, bytes([world.options.emblems_required.value])) + if world.options.tattle_hp: patch.write_token(APTokenTypes.WRITE, 0xD00000, bytes([0x1])) @@ -427,4 +431,4 @@ def desc_inject(world: "MLSSWorld", patch: MLSSProcedurePatch, location: Locatio index = value.index(location.address) + 66 dstring = f"{world.multiworld.player_name[item.player]}: {item.name}" - patch.write_token(APTokenTypes.WRITE, 0xD11000 + (index * 0x40), dstring.encode("UTF8")) + patch.write_token(APTokenTypes.WRITE, 0xD12000 + (index * 0x40), dstring.encode("UTF8")) diff --git a/worlds/mlss/Rules.py b/worlds/mlss/Rules.py index b0b5a364..6592a805 100644 --- a/worlds/mlss/Rules.py +++ b/worlds/mlss/Rules.py @@ -28,11 +28,14 @@ def set_rules(world: "MLSSWorld", excluded): lambda state: StateLogic.canDig(state, world.player), ) if "Shop" in location.name and "Coffee" not in location.name and location.name not in excluded: - forbid_item(world.get_location(location.name), "Hammers", world.player) if "Badge" in location.name or "Pants" in location.name: add_rule( world.get_location(location.name), - lambda state: StateLogic.brooch(state, world.player) or StateLogic.rose(state, world.player), + lambda state: (StateLogic.brooch(state, world.player) and StateLogic.fruits(state, world.player) + and (StateLogic.hammers(state, world.player) + or StateLogic.fire(state, world.player) + or StateLogic.thunder(state, world.player))) + or StateLogic.rose(state, world.player), ) if location.itemType != 0 and location.name not in excluded: if "Bowser" in location.name and world.options.castle_skip: @@ -99,9 +102,86 @@ def set_rules(world: "MLSSWorld", excluded): lambda state: StateLogic.ultra(state, world.player) and StateLogic.thunder(state, world.player), ) - forbid_item( - world.get_location(LocationName.SSChuckolaMembershipCard), "Nuts", world.player - ) # Bandaid Fix + if world.options.goal == 1 and not world.options.castle_skip: + add_rule( + world.get_location(LocationName.BowsersCastleRoyCorridorBlock1), + lambda state: StateLogic.canDig(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleRoyCorridorBlock2), + lambda state: StateLogic.canDig(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleMiniMarioSidescrollerBlock1), + lambda state: StateLogic.canDig(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleMiniMarioSidescrollerBlock2), + lambda state: StateLogic.canDig(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleMiniMarioMazeBlock1), + lambda state: StateLogic.canDig(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleMiniMarioMazeBlock2), + lambda state: StateLogic.canDig(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleBeforeWendyFightBlock1), + lambda state: StateLogic.canDig(state, world.player) + and StateLogic.ultra(state, world.player) + and StateLogic.fire(state, world.player) + and StateLogic.canCrash(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleBeforeWendyFightBlock2), + lambda state: StateLogic.canDig(state, world.player) + and StateLogic.ultra(state, world.player) + and StateLogic.fire(state, world.player) + and StateLogic.canCrash(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleLarryRoomBlock), + lambda state: StateLogic.canDig(state, world.player) + and StateLogic.ultra(state, world.player) + and StateLogic.canDash(state, world.player) + and StateLogic.canCrash(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleWendyLarryHallwayDigspot), + lambda state: StateLogic.ultra(state, world.player) + and StateLogic.fire(state, world.player) + and StateLogic.canCrash(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleBeforeFawfulFightBlock1), + lambda state: StateLogic.canDig(state, world.player) + and StateLogic.ultra(state, world.player) + and StateLogic.canDash(state, world.player) + and StateLogic.canCrash(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleBeforeFawfulFightBlock2), + lambda state: StateLogic.canDig(state, world.player) + and StateLogic.ultra(state, world.player) + and StateLogic.canDash(state, world.player) + and StateLogic.canCrash(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleGreatDoorBlock1), + lambda state: StateLogic.canDig(state, world.player) + and StateLogic.ultra(state, world.player) + and StateLogic.canDash(state, world.player) + and StateLogic.canCrash(state, world.player) + ) + add_rule( + world.get_location(LocationName.BowsersCastleGreatDoorBlock2), + lambda state: StateLogic.canDig(state, world.player) + and StateLogic.ultra(state, world.player) + and StateLogic.canDash(state, world.player) + and StateLogic.canCrash(state, world.player) + ) add_rule( world.get_location(LocationName.HoohooVillageHammerHouseBlock), @@ -398,6 +478,10 @@ def set_rules(world: "MLSSWorld", excluded): world.get_location(LocationName.BeanstarPieceWinkleArea), lambda state: StateLogic.winkle(state, world.player), ) + add_rule( + world.get_location("Guffawha Ruins Block"), + lambda state: StateLogic.thunder(state, world.player), + ) add_rule( world.get_location(LocationName.GwarharLagoonSpangleReward), lambda state: StateLogic.spangle(state, world.player), @@ -406,6 +490,18 @@ def set_rules(world: "MLSSWorld", excluded): world.get_location(LocationName.PantsShopMomPiranhaFlag1), lambda state: StateLogic.brooch(state, world.player) or StateLogic.rose(state, world.player), ) + add_rule( + world.get_location("Chucklehuck Woods Solo Luigi Cave Room 2 Block"), + lambda state: StateLogic.brooch(state, world.player) and StateLogic.canDig(state, world.player), + ) + add_rule( + world.get_location("Chucklehuck Woods Solo Luigi Cave Room 3 Block 1"), + lambda state: StateLogic.brooch(state, world.player) and StateLogic.canDig(state, world.player), + ) + add_rule( + world.get_location("Chucklehuck Woods Solo Luigi Cave Room 3 Block 2"), + lambda state: StateLogic.brooch(state, world.player) and StateLogic.canDig(state, world.player), + ) add_rule( world.get_location(LocationName.PantsShopMomPiranhaFlag2), lambda state: StateLogic.brooch(state, world.player) or StateLogic.rose(state, world.player), @@ -600,6 +696,14 @@ def set_rules(world: "MLSSWorld", excluded): world.get_location(LocationName.HoohooMountainBaseBooStatueCaveCoinBlock1), lambda state: StateLogic.canCrash(state, world.player) or StateLogic.super(state, world.player), ) + add_rule( + world.get_location("Chucklehuck Woods Solo Luigi Cave Room 1 Coin Block 1"), + lambda state: StateLogic.canDig(state, world.player) and StateLogic.brooch(state, world.player), + ) + add_rule( + world.get_location("Chucklehuck Woods Solo Luigi Cave Room 1 Coin Block 2"), + lambda state: StateLogic.canDig(state, world.player) and StateLogic.brooch(state, world.player), + ) add_rule( world.get_location(LocationName.HoohooMountainBaseBooStatueCaveCoinBlock2), lambda state: StateLogic.canCrash(state, world.player) or StateLogic.super(state, world.player), @@ -679,7 +783,7 @@ def set_rules(world: "MLSSWorld", excluded): add_rule( world.get_location(LocationName.GwarharLagoonFirstUnderwaterAreaRoom2CoinBlock), lambda state: StateLogic.canDash(state, world.player) - and (StateLogic.membership(state, world.player) or StateLogic.surfable(state, world.player)), + and (StateLogic.membership(state, world.player) or StateLogic.surfable(state, world.player)), ) add_rule( world.get_location(LocationName.JokesEndSecondFloorWestRoomCoinBlock), diff --git a/worlds/mlss/StateLogic.py b/worlds/mlss/StateLogic.py index 39f08e16..74ad5aa3 100644 --- a/worlds/mlss/StateLogic.py +++ b/worlds/mlss/StateLogic.py @@ -1,3 +1,6 @@ +from .Options import Goal + + def canDig(state, player): return state.has("Green Goblet", player) and state.has("Hammers", player) @@ -105,8 +108,9 @@ def surfable(state, player): ) -def postJokes(state, player): - return ( +def postJokes(state, player, goal): + if goal == Goal.option_vanilla: # Logic for beating jokes end without beanstar emblems + return ( surfable(state, player) and canDig(state, player) and dressBeanstar(state, player) @@ -115,7 +119,13 @@ def postJokes(state, player): and brooch(state, player) and rose(state, player) and canDash(state, player) - ) + ) + else: # Logic for beating jokes end with beanstar emblems + return ( + surfable(state, player) + and canDig(state, player) + and canDash(state, player) + ) def teehee(state, player): @@ -153,3 +163,10 @@ def birdo_shop(state, player): def fungitown_birdo_shop(state, player): return state.can_reach("Fungitown Shop Birdo Flag", "Region", player) + +def soul(state, player): + return (ultra(state, player) + and canMini(state, player) + and canDig(state, player) + and canDash(state, player) + and canCrash(state, player)) diff --git a/worlds/mlss/__init__.py b/worlds/mlss/__init__.py index bb7ed051..10359795 100644 --- a/worlds/mlss/__init__.py +++ b/worlds/mlss/__init__.py @@ -1,3 +1,4 @@ +import logging import os import pkgutil import typing @@ -7,7 +8,7 @@ from worlds.AutoWorld import WebWorld, World from typing import Set, Dict, Any from .Locations import all_locations, location_table, bowsers, bowsersMini, hidden, coins from .Options import MLSSOptions -from .Items import MLSSItem, itemList, item_frequencies, item_table +from .Items import MLSSItem, itemList, item_frequencies, item_table, mlss_item_name_groups from .Names.LocationName import LocationName from .Client import MLSSClient from .Regions import create_regions, connect_regions @@ -53,6 +54,7 @@ class MLSSWorld(World): options_dataclass = MLSSOptions options: MLSSOptions settings: typing.ClassVar[MLSSSettings] + item_name_groups = mlss_item_name_groups item_name_to_id = {name: data.code for name, data in item_table.items()} location_name_to_id = {loc_data.name: loc_data.id for loc_data in all_locations} required_client_version = (0, 5, 0) @@ -61,6 +63,12 @@ class MLSSWorld(World): def generate_early(self) -> None: self.disabled_locations = set() + if self.options.goal == "emblem_hunt": + if self.options.emblems_amount < self.options.emblems_required: + self.options.emblems_amount.value = self.options.emblems_required.value + logging.warning( + f"{self.player_name}'s number of emblems required is greater than the number of emblems available. " + f"Changing to {self.options.emblems_required.value}.") if self.options.skip_minecart: self.disabled_locations.update([LocationName.HoohooMountainBaseMinecartCaveDigspot]) if self.options.disable_surf: @@ -111,6 +119,8 @@ class MLSSWorld(World): for item in itemList: if item.classification != ItemClassification.filler and item.classification != ItemClassification.skip_balancing: freq = item_frequencies.get(item.itemName, 1) + if item.itemName == "Beanstar Emblem": + freq = (0 if self.options.goal != "emblem_hunt" else self.options.emblems_amount.value) if item in precollected: freq = max(freq - precollected.count(item), 0) if self.options.disable_harhalls_pants and "Harhall's" in item.itemName: @@ -138,7 +148,6 @@ class MLSSWorld(World): # And finally take as many fillers as we need to have the same amount of items and locations. remaining = len(all_locations) - len(required_items) - len(self.disabled_locations) - 5 - self.multiworld.itempool += [ self.create_item(filler_item_name) for filler_item_name in self.random.sample(filler_items, remaining) ] diff --git a/worlds/mlss/data/basepatch.bsdiff b/worlds/mlss/data/basepatch.bsdiff index 7ed6c38ea9f432dfcf506156c77e4f56bdf3026a..18d6b56e59b746ecb6c7f3db8d297e2accc305c4 100644 GIT binary patch literal 21812 zcmZshbyOU|x90~N1{qw2f#7aI2A80NyK8U;4IU&UxVwAM!QC~uy9AfuP9P9Sh-`ju z&z^VQ?%wWGUAMZcPT%^gzV~xwbmWxaa2QWB9^k($2l~IC|5}v)^kj??0=&{j%sNJ) zuTPu-;NHLguXX>=p*k;~Ij8(C_t z3dkIm6uTS;D9k_02Bmbv0fD*~( z7U;+>KZqk~?`4-AkdYNjgoP4n09@Gz4XyKk5yH@zWu*Y~Xwsw_!~Jxy4SE+)qS6^O zQ3i^Jh=(DT;DkZYIA$p*l%^v7-=-k5!4PIRArjSQAqh5)Sd!uap%Ef;0HE?hq5^p| zN1G)E)!?FkF`ytLLZtvuFu+f`gcg8u4gdxr0DyT)O@Mz8VE(@@7b!vsQdP!{?DOFA z3O+EJ6l^0NOaX)b`xLN{1g0(=27qBu1WF+v0tP@SgdyhtEhnJ{1NalbfWh=iC?vmS z;SoBHHXGSc8!KQ$kV7HNW}y)3P$Fdml~4myYNDwD0ROy+RG*pGN*6>+q& zMAweA+Da4A8f~?d;LT&IKFG0;qL7ABpnWoNjFe)-RLmrRpd${m(gIO*#XB8yYVa8e zLZp~!rgR0lpfSiUE%{cn@r6`)cy^O$s@~!L7b6^`%y$k>_JU#(dbF_^^d}i9@TuAsFK3S??El6s14iDQnZ%6vev0q>CH=Moh zcT%fex&FLuXBBwsTZLg43K?BWe_>DK%sIa!ZUq@U?jJ>)Yb9i8m9 zlR&T>U4uqM3oACNNq+vYiZM z$|~F)5RJvsaJI9jv9WVAtd{U9P&T?|F;<3{fTQbImf_A)ob!OS-fZ)c_Gu}eABk2y zpEG{H5hd@0$q_!xxyrfc*Z0-IfmHS-CCS^(?KhMU+;EwC*7sLelEpiGC3vQfr@8M+ z94V)uJ)O=ee!LsEFA{$xFN%QDK8M7mIS##CF&z3PvuK^+i(U+2#1hgW4ke0pjiVK2v@%nniQ|YU#AwM6 zCd@EHjBVjN0^MT6VJrb(6N1u^{5NsMR5J?M3pTm5Aq4UYm;p^G94?wQ`o8CU#7l^~ zwKE<8Ni!V+Dv9^&Kh`_=X@4!#y(biMJ$9(Ez+eLr(aR0P@$;ny6P!)zx=nxLtuNsr z_H6j^n>NQ?b7fIs{;Nw^#?mGl`C@iAY8puK@^lI2_oMP!J^94EQ`c{Cl$(oh2r=ml zaP@rYoS`JH>j8ppSWh^Mq%o^Uw=2zz0Cot7pjY9*;RH<9m zPVN^QTyZrCEZIKa!nE8Ly=H;mu;F&-h6mT(CRgit`x3UZqFp2fty-}3c$c`_MK$Y8O$30U za4(#4F+&VZ2*GcMM zPQ7R3?R}LApa{C^U2Lk6@^8apByyd_jUjnL)m`_;_;_6tn3Pm6n@C}wSK+}ez}mX# zh@_oy#O9si%kSJsX2e?{Sj=Ih)z4s2*)?5^0qq(S{qo8`&afn9rla4IMlW2&(A4>e zQ-|aXe@q|CJ`AQ~g!(WtlKAIxbx*bqAAIw3I`gjmcGW62QJC@tkQ?Q$)=SM-{`IJ>#wH{?>@; zkVbfCIKtoAbV<~fpjFgO`dx9H|!T$N$y%D#c~x}{?$Vue>fD6HBT zJ=KD?{qW6?*W5L@4|=+lzYK8Oc|VBqvt-w|4(Jsrm&sD}Y|8jj!yY7}l-jnId_4FV z>Mpby%Jc~w_A=^E-M|T6r}-?j`WWLXQ-*}mRP@9xsrbmudn8+cZCahUKz+A@9dJCh zV*Ml8{<|Al=dRhyr~yqy2s()r1_3xf51AF*mSgSAxBN(0)X;0gXknb=C!IE~TgX@n z9(Sd6o|}XDs+LwVw;2W%&O!_D9Fe1JJk_Y0xi*FF;Lrk8LMd4(G)v|rf_^3Pp8V9t zVNEujaw57iLV^YGuyBNcdUlE>0M~_cA*b=P)pZw_g60shW<@TLZ)5$JvW#3#R2#q| zq2@=#=%v`yCX0HEVkb#T6hik1n>U_R38MH>lqHExP+hRi*|X{CoCydj9!GFggqM_D zT6OzN%X#L?vC;>ww@@TAcHkZt2WeFjY+B@^G({^NA0i=JLm&!!UA6QaH<ixlM4yn8uasRzCwjpCl~wR-zk=yLG4&DqOc*N7+*KHpAbHl8s{CX7DH*(mM5I z-Rnq3FEwws_g*-&=KcOX8XtZ-Q9dnMtdju#lerfYl#3=v8bZfgw}aT^Ztb1bx93z$ ze9K|Y=M~rYD&wPbH`kZ+vGtC^(An>T@#Bun#3X0xWo~_5#7`Z!nG)ZI&oBAYRagaH z>sXFYJO3@F$Gz+RIrqB!tvS{&TPn#n7ZsXlvc{doL|%qR8CU{MC!FNliZ+)SDU``y zI4x3QIc;A{5RqIubB#K4I~(Z_-L|DaR%CEGPz`D-h@5?|1+M8>5Qdy_5qY}bPc;?s zBNxp+J0>gWG#~rVzcC_FuFJ^W5F9`~qYkL`ey4~t#gK}fUWhCx;j6u8L3?%0F!!Kw z3vccml!AyXR-kJQ${_!~GQ})+nJ>{eJ!MPb`&O(nv?JjcYjb{~Uwf{|3h>?62}8ss zmljmCF3-LY5tsgQBCe~@=K21`W4!$fuQ967OibQApHn;{1tltDuOyx(BkpkS>|`NB ze=Y8U;|RdeQDIqCn$IN(dNe;+?$cORQ;IdN0!4M2AlsK#Ba@s@7|M9n59=F0ump#M zdQ40|5cPwtz0Uf_No(!B*bg||!TrIosaoLv?P5*|Vslo|O2hau#vqH# zEJ)_Oj4g#J88-}KHg4F4MKjOqw!;nNTm7ZBv5ClO+g3`Ax6zuU>f% zms0F=0z^8K_u0LSEO=`|h83YvTi7{k9ivId;+|8%q~)fnPP8eObLSgRoi zA*|Leh0ZR#ZGvmy(yU>@4N664MaY2Qc(4>7l&-=vFH4Xy6+soTr%r+DB5NZ>%&Sz? z3EQAc8pVweBqVxZ@lCnMp?6fb{iE;HtH3W7xw6^j9}`o7U^Y;9$AqY>3zJdg>w$ZjMHDR2Wm6 z57yXecx{__nB^vA`3)CrS1*O4cm#e*41Z#Fq;88JjcuU3i1Q?^x(ctqj=71(!N}7g zn9n*Xx3D3kHhlODI?SO`B~lz**rh@t>oollG|k_<${YetaFf4gPqGtW0kPV63|*E+ zzO7=rJUxDYRy^>lN8&E;h4k3v#N_Fdy5Ai}Uxjr}R+a8-W_!j^Nkx6i2dDSdJQG+x z6f3~kD|9?WxA!#ph$9(Q3G|+WD=uD)_t7rQ(yEs1{MAGi_U*cxEs?ai#BVe&|2Sul z!GX}`&BKMnW-}_YK<9}<+zztEsyonnS?TlgCzcgmqX(VmKC1YmZ56Js911<$tG?mA z%+uaaUrB+_ZxZGrQN1xd(CF!T=mB|KFX(m5=wd??%9NVI^Yp9w$wmxqg=9d_-D zDuS>2o-N1vh6>hK6?8lF>t+~1>RdYYZ8ScT&>TXnVBC1-g0S($k0AxBj=ZW90umaF z{IoiES-`Zf$OnzZk0neJEmAu76tE>`-3Mw1Wa>O(p~^p3L-#=(3I!!D7HH_mNC>7* zXt0%^W|ik4RwOFV{h3(>U~&_M4AQWTxNP1ehhn=NVpa5EYi-NQ)bXW72c#Nbft-zC zD&e^WRE<|cHJ&;Ou~1%_6OpJ?Xfuu&=Y>d(-%EjkAOtjr85tMBc9<)-q$=YtwIE)C z)hZqr-O8gz31`+pr;gen43&zA=TU>g=Ev7k)hKZ3N)#%_=Ph9lg}6DuI4M5de-bvC zUJh-bSCX9&ooHZ`IY_3a0|*y?`_3(5cf(Y8ae`kIfSR74i$5{ z4-&*`$in%h<-2UCGjjO>AR(Q6ngbhNTBa^p##e-b(UrA{=_)2d{Id{Q1%=eeAe2@x z-~j;j&x!~F0OR0rHGqT^b<#h{{7*FhYtf{Zq~`w#<7j1>k5vJ>Jn_`!74!G;)Hzrs z!~{!=Fa%=Z+~%J^1^||1{|Q_G009NU|E=^NtqlPDC#&I@B6(gK(Csz$sFfD~x7Y0Z zHa5o^`gxZLsjP}lBFH^&7Il$xP73F$`*|8u)Ssj-wfSR!3%BZA&D`ftzp1EAMSpZ3 zs$Bz=T2lj(@rif7m6K5mh6M4f6(8yGSmPF8iy1)i?aqK`6X^zQgH_L0b>abg#^A5T zN!jI>t$*ykObZQ724bXK&`o}i%jo3_-BoS|HjOWCR&`wY4@cgNY4x{kx^p#u8TrJx;m~C~>R4jbw%y zj#x7CTsI{UP?_eG^Dv@W+$C${xKtf3zILtRcMCErQRTv9eR1USh_#aN#v(>(VP@b9 zs|AeUc}enym@J|E)4UbVv-505xlUrpkK(d@^NH%uH62~i;$xQdw>SAwXX3;h6tq{I z>?g*L8iO3TbDeov-t{4?%u6_bt4}d(G;p}k4S`N`*b|=B#n%tmJc#dDzYGm?9a}yRf2j z|6WPGI=z{9yXZhK(raToG`?Jq0Xv()S>HA4l!t(K7{=wb&&VmTP}-vC-iI*70f@;_oM4Vj z`>13Mx{_Ikh3v2Qz+u4O7_vBo?IG{nF`-wIpoX~_d*og#nls(!O1=A%4M5cwpSscU|6Sdk;fTLJp zW5vpCMc<7J;N?NDMp4Vb-jbK4;&s zFO2Chj6z+NG9V|VJS0GA3}MB{Bc>xjS7ijKfUxQQ$jJeY_rT}0tmFvnVshVNRQtUu zZddw}gs5V&M){_giUe#xF~+bofdV0ko~|mV76y(mJx*LqlucowNCk*i;FiSnP)nCX z9sp<#3F2@k1ej83$x;52CP2dg=t;k=U|8G3C{yh3(i z29L)r41)QBs0$T1K#HSSd&m$TWU~i(vfcA@!ywgrjeP>YQz8fpMkUbc35mFUNdRz9 zl4HY=X#ioh%gcgMuus`n=#7U7N;UW#2~96inyQO4SP$tD# z#$RF(6gOjOhZBM$VS|w$ zX{fv8g5Qs3KVvtNl!|829z=s!t%|vYqq^<|)_?a8rG6|!7lK$8rl8&ZN?pEa3=do` zL+1_kPn(|LPvSZlA>h{f6YUwKPiGvzRspnRoRXt`X)Gu)qHl*_Uh@A{BxY2+d+wzz znxR(Ge@CwoCFeg%@RyQIUNR06-Q{inhOLp9>XooZG1@{gCeE++h9de^xFt3$WZH$t z*-=5rNv2e*yCFJ!q@DB+_n&ah`8S5~-_~@3Mwg--DC}ASB%QIT4mY@i^mUTA|z;Ngg2bU^`JxV8S<;RUmbkzLnM82KP8!ljJ%s@UeL za=^6=x5o8H4tHZ_wboMAJgy}a{bj?*CQ1E!@FZxfwcRq!H#wq(2NY`S>L=kNIvLgX z6XQ~3fpfEpopsJ@Sh<+mFx_xQmtYLfb}~(=-QcY`CGe$Xa%ju2*609WbU=<&&;Q4q z$>JEMY8=n|KVMYFY6ta!L<2tynOMGZ(ji)ZUVSDHd>P#N-hwtMN!3anmny>(@Mo>x z?kV|sL%E*N!PR(=m3G<+!bCtClw^bqBsL&+qNk`fyuut-%S^i+jh`5EDmV zkD93=p3Z%=&#qzIO6+CqmH?^c{Ao{=`l%-Z7%hh9;)hl&tNEmfoN0ru}Yk zW$51R&5r<*WC)7YuPICX8QKtajP4qnq+IMGZ1kmG9uzTI9nM3`I6eAu=a@Bd_8bl$ zj~c*7hvOB|QV6r=$;T6RIbs~EBoozaT9+(l{f4LVR}~`${v_!`bq%4_EL2B=QkCBt zsqCTT!BfL{LmcD*Q?Z`{Wo|zlQdQ%%dLiYvM2+-VH+sT>`1;5`#_x5r8GT*}ayN$= zsg#zCO+H~9HD4&;#;r<`Ezma0_Pslskb=pk#<_I|)^wqdFt?@|>TWa$yrYxGZ`-=xr$>?_RW zrrU)WJD9OI=D)}(UuW>i-;GJOzZ`Hf&>Q;-M7fBrHau?OI^nZC23p06ABNYJ$?D+! z0foh?|03!Wcin&HqHBsJs{l*%V!ff5de__&`CPc9cL3CfIDdJsq^pK}umes?UD*a% zkcFE9d9oemN?2ZEY@oTiPg|OdhT;suQHGBi!dg^qzUgvg3CyB$0eTHJhfZ!#+QNLf`3%#zGeoe1bjlKLc! zsEL#j9QMWgh31mBS_Ju#$?$^WU_7lniL6Mr^>pHaclY^5dQH?J&A;-s`SCk9;(sZ` z%Xznb!4&c33K~lC?Tq)C(F3oemxoO$It2O2lAB7%YvVD#%*@L)=EA%haI+W&f!mcL z!?IlDq2+E#z|5f-QaQh`8<7uKIn+!qe<2 z)J8u$)r50ymnb0cWWC%I-zPyTIRXNW?>7vJ?1g2m9@`YYfG3G%4@fd#JJGe|zmPhR zGDk=!Oy2%7c^Y!_v zti9IH4F@E|9Yh=>2$QuCv5n#m!t`B}g)h;mQ|^rHSkauNl~If3*6AB9+-oq-?FiZ@YTHWd2gTMBhV3k21&&f5l$4T`S9hLMK>#_JjuW=>&XT`NVWI$ zKqz7ThNGr-t8yOGpVkb=Zxf|5R~6$e$g@&~uqi?q4Oiqu@LkYB4NhT77c|R9!n^$I zjTgm2_-ecGnhMRXYx3*)Hhyci+l==d5wX~G`d)}<5@F|Dj?u`da5&xva;bL%D&Rdj zREq4N%*NSt40-PElCsy6@!xuVxX;pZ#=HqxcXu>SzL`6B9{HK=BR-xS$S{I%$3JlJ zNe4IBs$w$U4*=8;q!)$h%4)t?>4uv=B(2fv-+OC$ai589`%9D<_U;7kzKX`D-8e6& zJM~^WOuv&b5ypo-`xl2UUM$e5!H2ASlVS<&b_!mMuh}B3osMAvdf(k4oT0i|zJvl~ zwHl)_pY68Weo#GaUK-*30m@lgs9Y@}3J}67i=e@-Z6TJA#hHfp1~o+0r#aNR0(ptl zTlT{oPokMaJXrMe3SvQP&Ok%!RBVfolAia2vBZ*FLi+d;`%2|gU>jSxq@wjJx9J}M zWT_puzMHwj0E$?N*dotrV|uUr*2@fSQ97Wp;i}Dd-U;SBvcWscro=@jES- zMCpn?EjE?k;-tG|NU$bd8QY|&ZRFy*j_}a!yoW=!Bx%t$-r6yNjl&}D;YbG`qiE2R z#}D(OB*Np--`0}V<>VD9gLDF^U+)yEUp)kSvroQ-7l%oR?~z?Bw%7(0Y}96VJ_mp} z=c%jCaNbO*bess3yejo`T;CHAAtX?Su{0s7CV zqJ*V^xwTMbT`Nl!W!a#R9d|~E+a}cMC-Q}T59tH12_m_Q+7@MU8)`5V4)gg z6`wf7$tHP!>3uvQOk<}+EskrWw=LHqJ?SgQLg*Zyk%s}l0U=fG@w|W zrloG?!_I~VdUe?&W~<6W-l{h?8`b*B7d0%m;_?jz z!RDsi8nO4_=02#SSAkVF{q)anv}%q{8G7zyzo1@Qrd1D3>zyrK&F-=vRf6lPjHzfm z)K=cv-PhT)jVmpm@%=#Z1`)% zadE%GrRvDVc*yp9x2{soQ_sr9)mU=61w0ToVicDie4a)CTe)>Gyq;8nLs)ba*K8D( z=yq#3esa2cL6IoKe&J={(yYGQc|OiaBg~-H`Lg;}?CHYxGJ2;v{HM;*j$}f`9AT({ zn(vb!CAqR)YjtuWgEonu=%J?kq?TTd;Ok02u%xEZsv?@Uft(i&-4}5p8keR0yMs91 zowhixb;##%+CKGPXAWJfCjE09v1ezl+#Wgjy;-_bia$)XPJX;Aai~3awmu?x62g}I z**cdzBlI*J<}iQTNW1vLf27;+EUdp`ZeeA`Zg+oGbN_{@DS|Y2`JYR;jenWoptle9g14|Os%HFdE&*OL9gXIxf{!w#t8ZUaE0_Hh9?OcUUC>#$ z?@jCygT6c(^{L4~xPC~f{Sr}U;^$=-{h@^E7kAYdd(FnjaDg31SyqSSItDy%43by+ zao^ON#`itC9zWVV%ipKd$J+SAkWp5DTQq8aaOHSEOk|-$>)YW-DUQVI z`nHIM(o#&;hwcEva<}u%$L|z33)GLE`J+Zd8npov*`vKAe(&PBTsBdNjL7g`xA!sX z2{jar%NQN=eK5}UZy$yjUsiOOyYxV3Z^1g$G59VnNnSkTVJ_Rf}&tWC)6xx_7uq)lhj$`92>dsY%g}9s_pvSmq2W)J_9ma_nx;6L zv5+~A#A>i5H8W!eq>*igkqh!)jh3Nhbi{w0|J>OTwbzr=-D5G-lw{^cj>{#ovq8Tr zI9at(uuxDJW|frLc~{-RrIEHDuvimXrox~6%e0hCEZdDMpdqCQ_kgppET68w9>_6_ zpTg@4DRBKrmJ%p1bPuYG&8fzaQxX5q7$ z<{j!)6eS}3w;m}k+v=_cr7Ac_-jtuI6%6Zeoor{}Tp|8t?&~bLkZyJ;nwBcqOYT5l zUKLUB>Ags_7b*3p@aDj@OW+ozAVU=dPLC3L^icAy)VHVrHreO>h)tFE}|TlT?h4&f)X1^0c>+>Zv9p zO+=v2qvzfC7W=w>_WG}7kRq-C%j|YX`27BgXG_?r(Bq0AF%Dy5_}A~O z5_T74zYmMbktSOiDZSsW`^E`<+dEIge+Vu5ll{EtYMga`M10>rC?&Oyj?Z^>kD%mL z)AHzAFIa$E2YhJrJn~C9*Ebnm$5|bxD{Pb~<-SUp-f5&@h5oG-ze`Dx7`9ve)TvUi zOwO&f1{tMj0`kUL18l6SKt2r^TJ1rA%HR;%s7+}UErY5kR1j()Kfkq#k#~yOo1XV8 zF%5IC1$4STcF{0wch>)m#614qi zw$1s$qLkMVZjT2Z@iflormbIg_VblnFU1sn0$6i{!cT+E7zzU8{=R&VjWw*DDki?S z@mh(-A=C)8F|y=jo8hfGKNIur&k6Oa272$nOQYAJbQTZI)6&1{C#@X>bH&qZaVf&a zNaR@^npG*!OB&WSMAT*fl6%MtYbO1NMg2FKnp`XW0w5Xx@PEUo-+zDq*U-)Xd9lYN zd0&r&n_MkQJbX2kU`1Ilud!s;^D5egfKH!Js-5!7x0_v@dLGNoT303Wj{I=WT_4M* zPRnCAwPn(7`lg?E{jWZXh)vWP@GI19cHf8|aBg>$YDn7C-B?zZ5|&5-&>_*$EvhU@ z@s*)c%lE|e{#nBg5>Q9qP?)kyONkn#q6IS|Z6_y7fTGwgl zspjxO$}8^Ym!!+Y7YoAfC;cEuH8B1P6gEyN=dV`mFRO;8nic=A5>x8mY?S0eD4MKB z;P98V`pV8CYYrm=|DH1XB3#tXR3auf8-h?~dU|XdX*}^8$;6Hj5XDAo;#w} zV#=_EkMXBLow5=*5ivy;^b~>FxDgpI9G|fEpwqT*Ln$Efbb(bJb zbU2g3?&&2Q(uA9S#}tI9L~HgeC|DLmXd0xppT!{5&no2J*t>wHQ9i3HBaPVgcMG^9rbT~oVTd}yG&bES# zYS&@Y=2q^z`b%>3&DM@C1r870joi-FoJvE|jFxF~!}hoQ^`DEJp!}Y8+**yGkh+JL zsvHkd>Yzs0m7Icf9|*KS4;y0EGn%k&^il2%Ah$^+Jl#?!q7UejuB2b6j3>e~FlK** zY`-i2aoz5fhBNyk@Pji|9?9CfZZ{4tznY=Biejs4ly^pT3)QY0zu$X1``A5-?-VQO zJ>G7`pHo0F?PoCjCk=SFnrv-;+((2LZ%v zyj-IpHxRT14B~OAE4(Kx6qI=cQzYQp(M7(;M6E1c(6DxsgE11mjUruoZzER?6TGi7 z0vQvnsxD#(I~dEN@WMg^eQXTECvDmuwo+1{@(mNI5yS>vo|HPwMQMms=|w`ry`-R! z@f96;UUg8A96CsQBUN{iP_t0IC`zV`l&q^ULr-wn<6Y}|U)}KR;^AzFbwn2|PM$}V zhBmOugA?SrnQ@y@3`k z{FRl!uA5WGN-sM^(w;e*Qjqs3(TwT4D%ggejm5$ZG>k&-_JJ2Ce4kBNZ4%Mud@<*i z;$yGTCJsucT~mAuvI%+<^ETSM)uUK6X&(Zn$_DOs6r-0+X+6o9s!9xeG-_-;dWD5i zjr$7s;V^88A@HF*fU(A2V8|GImL)i~5sTYQKYf8I?-Q2o9=b?g$HKPcQ7ZhxYDlj$ zQTwg%Clbt7X;ng&*if>ZV$Yo75r1Ox(G`xihm2nD{0Zh7+1Ii_-Xxn7Y|T;+KI= z3x6o3cVT4i$C93_dMxz=_-~x#umVQs^p<*L z$1>9dE5cb86joZ=kEF@v^e;wM<7TFE8&JonkKD@e@i)2J>f^R?`e?D<*H95a6m2*h zvK31~LGmR!O>-LA$i}fZU8A7B^fepX6E&jT2P`y@3$=JA`@8w~B{}SsP#GB#5FpAb z%39S34+_~tY2i(=A^|rJ5-~39HscWJ&eIJu7-hEH*4D>oZ>r-3dmedkRk?p`mh; zY@y!O2<;HG&b=dcXwq;`Hn43ZW7Vt@<_78K9V@9bbJYVal(*4SR`+weQ&n6F*;|3k z&Ch(SHsBg=!rZG3Iwor#&WBV+L1ej#OmIBqDsz$shcUmfA=_5-%8uXVj~j%pTgD0K z(2tIawbZ0M>_pnQMNX|rJDm}f%>qi1*_PU{Xpc9u?|&lj6!Rb;_j%{=Jy-OeU#5j3 zfpw!u<3JNLCWq^i^wN9n`Df}|*^d^XW?CV$yj{Td!p;L66Ng6IV+RyFyOcA1&=C+1 zk$^^oWZFNY4Rhcbv-W@QAGeiAuRtx4c7Hk{Ii&h&XFtixs>U&HG@KaU7i;BEHco`TN8~sH zG^C?WR(h;twD2lcSG3SE*4A=ruFI!Oao(S!b>X3db1NPjtAb_r6$h>pySMmuTt_nQ z#nwS&IpJbK2pf`bh|&~x)XLa>Lre%@=n9*cAG}C&ph-`)B~?VitsBGB8fZzTmnkIJ z^!3%V4fi5M>#+-ww#_0JcIms@%gQS2lY4BzFX9*?EQ>JTst?fajS^OZ1|}3OWG-~E zff4f1-VP%YhKUueWG(ew*Q=gKm#7mbvhdy0!Se%MYjXFM#a0a0SmbjVCQ-=w5Yg2M zxJ_S&4QRg+S+)I)T-I%n&d#>u(4M3^OLxSXH${|==VSLQ42@K*+p=dBRao0zJPc{@ zEI0f22`D6mOGV(?!Ov2`H?juVCgcHzBlf0^5eCh6BpB@Bry>>@LssJ!go<|Awv{f+ zYPIerXXqEXIP_m+=uxyH`_Mx6HMDH>Ehdv|bCQMvLvg4;m$MYQX~(2wcIE1782aPv zUf7U`6}dF)Dc657z!n|G=jGz+t?VmIsLE*%(Wi}%R4{ds=rM|{GO<+J6|~Gn{Cx5e zDjFEf2I)Jx^jGM(qg`73L!5;j^MV@{-QG)lF(lPZK%F>x`7wzd?ljTwM9~85bZOW! zK?>Sr@sDnt=~}pE<6A&nJrkgg%u?C8>0mbMN|d$&IW3Dokws~7&Y?EaeO^b-tVGl< zZP>xJ0E4yP&c%Bu4kLm$*k!B{;F6!HtCf!tf5fq>ne|Y+R4ytUIkzdwg8fxrl#$@G zjte8WuE)W&eRTWVTc5WljKkmWU{vu;&V~L;-0p7PznFGk=8e9edi?hDN>Z>lSn!(s zdQ2QvVwig`E89;JmD(*Hv#gcgM620Fg+m+_W@=cn4Wc-q^a8#E|ClALL-5-X7# zw^rTAE+fwh9nRo+@q**=wA|OsAMHKu#k*NYr-ThXjS?4Yfp4IiGnH!s%%=mrS<07@ zI5DM?ImISn-;MkT6UPR!zAc@E2s6Bt`udRs$x3n9_-nu@pG{!=7{L~JZOa>syivYf zt;cz?M74tG_L<80^jyQi?=|q!oaOiAz)gnJQ&^)PDZ zjO?i1gmTLoQJ$$ml%w@Ka2~HHYiJxi&aQxVYeHx{Q0u!pcIE4Owbc%$%A#hz9Cvo% zIJwYd&0O(s6=-3!Av%LYw;RdU;4lNCa$t_Qhl*vjCoKMsUVk>c<~PmKY_kCZW!5FS zb#rU9bGSQkZfR=uc#EB_jN{hVQoL@etTEqto8XOfM`+5B?4J^AVVvmg(nabrSFc|o5ilD*uQfq~=d zi++=aARf-j($R6oX~W~l$S0SOi%2j<7GyKfOxIntq+;?SGvdaiS@BpgIB{`rd~%|` zxjnZ%(S*S6#$T{9Qr?;U7VAZvTzHS#n|PZYH;?AzY&lNOg-J92twOY{gUQ7EP$X;B7530Cpp8Csu%*Ng*XNa zJEdg&#HycN9R?q;2I{SbX{QE24y=o`gja$@@pL#*a&WMq~iH8 zJ7-qo2Xb{FzpVeD2+d5p`Nrvb?*66Jcg@}E#}C|;HojjEWB@_tC8_vM@L!3W(~E&St9#4G*3k#O6Hh<04@3s|Q{O!i1c>hUgZVAF z>-Q@a%BLA-;>lq^z4aAbep#x+OWd|b>)y1l>z5+-B|WqKWy(&?#!=s9izZT0gfC9S zTPyQFZY%%Xy1k+U$e`+Lig^*IqwdC+l{^8?lO|9nv74LmsxPgpV{oyMct0n z;GuY@Y7iH0pp2N|o&o?_VpJ8<+)jj``Hc1dk5Y9v3 zEzA>##?R2kKC&N8Tapp@bT%Na4=vMKp*uP~`4Jj^_KW70Yt;m- z)m)yuD@-l1b~QjYsxk62->k7(hB+1A!C|mIEmh^O1guwZN-^8?{V=JzDWzWJm&T@s z1h2tTHwVq>0l1(uQ++yF%xZQdrma(qDaI$OHSciL3ccC&U8Y*c)o0zrid=zk@pw>4 zp3LizzLSdgfF-_nN#|r7_)o03f}qHcl?N*=<3YYyC*ASyaH!vXYrTG@>mbrUr+N0m z-g~84JT*yK7&w?GFyrD9-{jc1E-*Hng`^6(^h#Vfa&?UU_U-b%Z5@z_m{(pAdNF%| z-Z6cZ6|_l~%7H%AnvJ&~D>KDz=^{hIq6H+sC_cg_aClP9MS3N_n_hVPhrp9y6MFD< zm22;mUvU9S(ZYxta3;+Zqod`l!N?2^c^bT@4i|5TeMKdfZ?=m6Se>55`Wr>{k-#Ru zs*{W+o3V7!O-BEzx@yKXM+{%oXtM64$(4aj5fv3(o}`h3kb)V^;8x^Mc96kqO_0F$ zQ!6w@hRIi$VPCmq=T-q_Ui;Gu`Yc8kqZ}v}o*|r8VU0oWB35Hs>QCseO^8V`B*l$j z?5M`@Xl9m2m0iLMCAdbSL#E$e+86{T5V>t;ao;QRp|JXt?Q06T`!d48OA9d^YbFn} zO|MX`NG+*M|K@00*<2TSioyKt#2NGo%d58*?CNPa34#`Z+`fP z=gc%aGO1_2I%vbvF{o^*Fm2m%)b_n)c_7!wP|4RhVE#jEvDu07lSL0-gY^U$0XLO8 zbOhdgx~T50Ip#IlXnu=>X~IYhCt@n9B-UYd=#!q$zBM+z*_d8!pp8=IF(oRs;^WGJ z;6bQz$;k{9+P6RRHu(Etl?~n(hMhCf1`NgXcFvJO`g!kj6)rr5YdfCR86Em>&aI_H zZs})7e4i&j@Vq^6WkKh+A`J4KgN!yMt{-`d=79e)(M)cwY+U8+%;*mM5U^~Em0hib z%c{5rpiMD=bOFMkKh(~+Px;nVr+FFPrbsvaf=E0w%Qf<;B16 z+B4en412d|qF7u){X9H$W6RYGJg%b+7`W{c(lqP^)|tE8NDW8%q@ZZ*QUH(1@hQ}I zrgxjVXMc>XvN)Yd*{v75oa#EHs7vD-E)vQO4jlM|!R0>k8I|lN*2R=TG=+fQ$ z!y(JKr8%Uq?mD=~dW_%?m>xLKK3V5ZY#TS*#^x|)By`EmYkRlu{1>_B7EAT_-@K14 zqrBU1D=YLWKGT*!Myoh8hBu}J?d<;QxAwL6x7NB+WamszpRpwN8PLyYGb#jX$^6%w}f~+W+XX3HmlC`E9PhVw#q5ddA6km9f76*Yva#G}W5v ze+5|-rt6n07A`DUXaT-+Bv2c8;b5(0!D{%Nw|%Y{yi#*g!7Q#yHL&z#H22b+v_RAl zX`dR>A41ba?#bq;=damik9@UvA7iKUiZiS2J5KYURo;5VUoSOu1R`KXGVt$voF*Tr zep6e+4jedep0_{HI{x=)7}ENFXc@_SQ1AAWRjsCT22=u|eRV^KPMY?2K$4rGWbygV#B7mo7PJKR}xC<}6^LTpHUMR^k z=q=Lpf3oZBZ zPxa@2-oGzPzu}U9F2oea7YB2%;1}JjVAtVt25D_F+37Ov+DuZ9@jzPIRVy~hE01_xln^L_5?rvu8?-*vrY4V6eC-y&{PO)?bQ z=II~{HF?eN06l!}!vr@;0|R0g>FJL-cT3&n{Qff0X!WT*uD3lbB1 zu<(xW{|*TO>@`UQw>TO0Hk=yobdcZnL>H@GxB78ZA$^sDhbP^aXrt)W`C6D0Zrk)<%9(Ciy$u!NN6e8!Tf$=AVJ z+t|97_bG}`k9z^jaYsJIy)Ir2Zuhgq^l|u^n#mq??*CK3xkr6|e)9=Vxvdsqo^8l? zKDJ#dYw8k_ioLB4{?H+5-Qjy*BQEOq9oB}y^_DDW^byGnZ}7;UeHvB{%Jbf#w}pw{ za=d&UcE7zXruq1e>=Sd3l554zJ-2<-Ega-UG;(gsc>-*j<()059xVBM{GN9{u5Wcw z+giFZn!%$VLN*5CgU~9YaBCN&=H_T#8@`~%%((5H4wnAwg1n5OM_(yxS~!kqB_c}N zZSHmx+gn-o^i+Qr}cQ^}n^ z`8-<`-36C?W{oy(mVJF*lDP_d`wfl^^ID`YZ89z)_WMcI%(mEVtY+QC*3}~1@gHyb{g;d&kuD4M>EacrV?e^{1t3@uaC57%YZByw~(bB(j#^yg+ z+dgxbdtpY&S_mO0wQkA17h{oYGcz+YGjl+6ixXDs<>@aqwN%bd-v6Ri{ftIn(bs8t z%z6ypy_IKYnSKmq)3rX7RJdvDf%#J={8mv+XtUSjZL;RTb8&K>F=BQUlxbhB^|CQ+Wfh@ySTMP zN2!Ibbz@1iMz}`m4)!sPTl6iXRUthK7yj&Y`5malk=$&cMZmOas14UOm$|Hgv%uVM zvcu=kwA*dX-4?P$!p&0zsReNE^}B0nxSpc4zFz(|61ed4 z9(v;zc}uV$grCBHUs;2DP>O@pE{{`((5#m^OZIv4#?=)?Qz*1@u2_t`naUb{Yy0Uk zEt*My*1%FO%W=BA&aV%Gv@Ky!GfK7cR`)U;wbxACQy5_b2c&yzjDwe?cuLQd{Pj|% z6ZFY!&QlV_!kFdTS8*xaR>U%iDg177|5H96VdCMxQ);p{TMdUrt`T2f(;=G8bJBc* zU5rX!lAv%n5hpISXZJ8VsGV=*KTFZ3%q4AdROl-oOnli8MvTn6CGGf7{>7D&SEtpls3!uGbd`h1en*LrMO3VL?* zyE=Im(;96eq?|@WM5GJyx`rBKJ|A~YRW)0W2eGx9bS#w&2x-#S-@nWnhTZDG%ynlOmOT-b-^OgQR)np znRg6=;W;Ud#iJhRgvozJz5a^=B(MSr;_P;0P?`qzvCydb?S5cM?P}TI?_A1~<@q zEWgFtG0h9R#fmI+AjbO5o%CY%#Qn^_&4g**qoK#3nDM|K4XB2R(hG3#LitL{e<%v$ zCk!`74JXKW6Pku9EPY2A%c5%&#RXu@#!5P5H9sEg<9V};b3=~<$GYg4;dGmT-kaXU zzl_W5=jP{Tf#+HSJ&9_2gFZ+wG>c~oOS9C~K3)V86wkHh5!u>KyDsh1-I3wH4-H5> zqhEo4nwM57cKmP9Cef~kWB#>Tw*sY#Nf0szBW)TS>Pily)5tjZG_} zvy5mTCevpW&y8sGrVf5I;CR|8>L5yTZGEDmpNL-uPUx0CS_{`Xaq!% zNH{!*%k2j4#X}jH0~)O+mQ<&X@G}~_TZW`b8y%yXJKuw#!&KFB#%E&o`qlX$0|eSy z99k5wf0BQ@{A8OAA0#pq_iV72ter#5%<;^Xq39{@z0L~xxZErOV8$0MhlI`=-Q-9* zt+BcI32?IO_&yRUCer0Xu35W9jy))x!l7WCezKF)hl{Sk8hLiw6z}dBJ8`Hw-WY+3*-xtEHQM^!Fv0ywe67P{?$@T9& zoxDK4>VQ{kW$M>bsO)p`a&VF}0y26hdD3122{UOd;@iRZH9l~YhjOjpp}J?^HN;?d z&3Ftwqg}~i0n1`1QQ}C-i*quc)7tt{8Blj!+NDXE|02*!%!4EN=aE{E3g<>kmwTXW z=yZNds(7%@+H6kB)-z!f0%IHi=T*pxBM8?mb2FzcVgRN^oZ~@PyR)HG{5R->iy->q z);Ui}$(b8D3*R;q+l+e)z* z%s2xeh(@z{Fy2NR`OSHbzS36iIdiRj#(!F`l5Tt-d4HYW*~UxKd#rdV#+?$yM**N3 z(C*&meK{9BuBna^%s4%R+oGKy$AnFK7n?!2P>u56SPRAfQ+(Z&b6Nx8 zde7YdMe9=^4=vMOv3aOdsnj&JME?>?qBa3-OTTfN8N|CG(l#{sAhH@}bV zd&|k-kON~I$-6#(?WC*!^ryL+y6dsSSk`4{uWBw@hVX`9p!p*h{(wdlX-yo>FSYW$ z1s#K3tt4-I{_lx1-SsIXnrW(!5tpoy@ytM9uT{OEH!Dhz`5UhXkROA=)b#9kM+O>< zFES2b<+QN*M)8Lc^Q`J&q-l>>g3%rZrZMXJJ(Kxw4FS6xDIs6nv(Dg=b$#66P2 zd>kW8meb_I=x2vriia2n-!l@+!uLq|x3;~cpLM64VbLs2s;;X$OCJDfyYoNCN>X>S|t~;i&B1DN2Bt;(> zyE=d~u6|GvFa@CVNXtii#;^2v^I?ISY}UL`ZZvbnSZEB5m5D_4dO*gc#?IW+W5;&C zMapWgRE1Hk2?smG0G;hDy`?PlRw`p6V2_0W$b?q#I9oItC|zb3U8dQG+9`c+GVO=^ zwqk=KaElw~{ZfcI3)Z58EU!tuhOA2HkypE(KT$&6%UgQ`hn6*J)LG+bq7MOwa|+uM z80z}Fsjn;BcD=j>9*V`r9fo~49`z5|H(c2K-BaZL6MJfP)SP_pkIbESoybxTlhbaB z)n_5>w5KL_G;SjL&FdfB^j|;#fFdUCtBs8M^uw~icT6zGP)%=6)IEK~-iQ(7TI%mz zw+?8eBEbljFS5t0AH}gJR(EH5rVPxN!BS02&cs1JP&7`jSsvX1l};as6JQa~ESt^b zd1*eAb~vTL=qOw~TEa%xHp{v=cCLo~IO?$m(igL6>loVfWcyC!YqcZn8ryPwH>AbW;%BqZ<<|RoENn5l|7r3w zy3dJ+BqG%$YKQll#2K^DE=?ICH;?j;i?F9lizU2f*U- zxZFBk`ibi*ykuY{NP(N;n~kQkv#=YGv_7>}5wf<~vkM3UAb>bpfZpx!uqWKNg!pGJ zBW${Mxa#%V2OM0fQR*Fmy*=mLIM?R1{n$@H5tCs@Q1KkcF!i;~P&E2)NY0C5+YN_O z@pBxq9i~!{kqO_F?GF{)&g&uV{>cUQkxhom0A>ymrnbKI%RIeU(GHtKWu`1}MQs0r znZ2dJ^LF#GySqI3d=75olQ-`A`P|We92(Xte-3YIJc|$0I!`?F&phst7@j^|u>p0_%B-?Ga+ikYY zWttQOxt2wP(pB)L>kXuum@r99I;G-qEMu=AakF{^WPU|ZHl#GUr;@>Nupo)8ZZn;~ z?)(o!m(J%+&|qiNZ=p@A`x9o(n>KHZ#rPw#K?nqW+8HvWMbJ}2LqkJBiy4_R^)qu5 zsU@IO7>+;~v$w}V+IFjR)#Y33T(W1oL1qWMi6hM;SXbddmq?qE?;yZPocm&5FtOO z%~G9O#-$>`wG2UuF?frN=P>BgpVi`PxgBi|mkqoAiH+J|%`vr8F&eE1Cli;;jl{;X z;x5uw33o3$YNY~dS&V5?&M_F5 zYd_Vzp49X;Q7J?xrKqqQZK}+Fr%UDDewAU6=uMmA|0XmcveCNz`>gCVcVERT)t!vr zt%}J0n-)d|?31J!=Mw{-bb%4c1{Vwm)W^I@%j_x7xt}#;@^JsVcO>Lc<}O4B4gE~+ zCFtxT$xZn6SBtjcS|bib36@C5hWX}<40L7<2Y&cSdS2(&>Tj2>>P4^^z5J-t5H zK!YBUh<2XzvLG_LRHR-nCpTN|8%r}`Y+j%|0GKum%N5cqY-Zq%bzarK>wi{hsSx67 SIR9V&i@744C`e^&QgDD`h6H#3 literal 18482 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