From 3bec40851ed38cf84955428cc18b526bdb702a3d Mon Sep 17 00:00:00 2001 From: PoryGone Date: Fri, 10 Jan 2025 02:54:27 -0500 Subject: [PATCH 01/22] Functionality and first logic set for checkpointsanity --- worlds/celeste64/Items.py | 18 +++++- worlds/celeste64/Locations.py | 17 +++++- worlds/celeste64/Names/ItemName.py | 15 +++++ worlds/celeste64/Names/LocationName.py | 20 ++++-- worlds/celeste64/Names/RegionName.py | 13 ++++ worlds/celeste64/Options.py | 8 +++ worlds/celeste64/Regions.py | 15 ++++- worlds/celeste64/Rules.py | 85 +++++++++++++++++++++++++- worlds/celeste64/__init__.py | 27 ++++++-- 9 files changed, 203 insertions(+), 15 deletions(-) create mode 100644 worlds/celeste64/Names/RegionName.py diff --git a/worlds/celeste64/Items.py b/worlds/celeste64/Items.py index 36c9f670c798..b173ebc69118 100644 --- a/worlds/celeste64/Items.py +++ b/worlds/celeste64/Items.py @@ -39,6 +39,22 @@ class Celeste64ItemData(NamedTuple): ItemName.climb: Celeste64ItemData(celeste_64_base_id + 0xD, ItemClassification.progression), } -item_data_table: Dict[str, Celeste64ItemData] = {**collectable_item_data_table, **unlockable_item_data_table, **move_item_data_table} +checkpoint_item_data_table: Dict[str, Celeste64ItemData] = { + ItemName.checkpoint_1: Celeste64ItemData(celeste_64_base_id + 0x20, ItemClassification.progression), + ItemName.checkpoint_2: Celeste64ItemData(celeste_64_base_id + 0x21, ItemClassification.progression), + ItemName.checkpoint_3: Celeste64ItemData(celeste_64_base_id + 0x22, ItemClassification.progression), + ItemName.checkpoint_4: Celeste64ItemData(celeste_64_base_id + 0x23, ItemClassification.progression), + ItemName.checkpoint_5: Celeste64ItemData(celeste_64_base_id + 0x24, ItemClassification.progression), + ItemName.checkpoint_6: Celeste64ItemData(celeste_64_base_id + 0x25, ItemClassification.progression), + ItemName.checkpoint_7: Celeste64ItemData(celeste_64_base_id + 0x26, ItemClassification.progression), + ItemName.checkpoint_8: Celeste64ItemData(celeste_64_base_id + 0x27, ItemClassification.progression), + ItemName.checkpoint_9: Celeste64ItemData(celeste_64_base_id + 0x28, ItemClassification.progression), + ItemName.checkpoint_10: Celeste64ItemData(celeste_64_base_id + 0x29, ItemClassification.progression), +} + +item_data_table: Dict[str, Celeste64ItemData] = {**collectable_item_data_table, + **unlockable_item_data_table, + **move_item_data_table, + **checkpoint_item_data_table} item_table = {name: data.code for name, data in item_data_table.items() if data.code is not None} diff --git a/worlds/celeste64/Locations.py b/worlds/celeste64/Locations.py index 6341529da356..88183873f311 100644 --- a/worlds/celeste64/Locations.py +++ b/worlds/celeste64/Locations.py @@ -15,6 +15,7 @@ class Celeste64LocationData(NamedTuple): region: str address: Optional[int] = None +# TODO: Move these locations to correct new regions strawberry_location_data_table: Dict[str, Celeste64LocationData] = { LocationName.strawberry_1: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x00), @@ -74,9 +75,23 @@ class Celeste64LocationData(NamedTuple): LocationName.car_2: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x300 + 0x01), } +checkpoint_location_data_table: Dict[str, Celeste64LocationData] = { + LocationName.checkpoint_1: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x00), + LocationName.checkpoint_2: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x01), + LocationName.checkpoint_3: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x02), + LocationName.checkpoint_4: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x03), + LocationName.checkpoint_5: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x04), + LocationName.checkpoint_6: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x05), + LocationName.checkpoint_7: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x06), + LocationName.checkpoint_8: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x07), + LocationName.checkpoint_9: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x08), + LocationName.checkpoint_10: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x09), +} + location_data_table: Dict[str, Celeste64LocationData] = {**strawberry_location_data_table, **friend_location_data_table, **sign_location_data_table, - **car_location_data_table} + **car_location_data_table, + **checkpoint_location_data_table} location_table = {name: data.address for name, data in location_data_table.items() if data.address is not None} diff --git a/worlds/celeste64/Names/ItemName.py b/worlds/celeste64/Names/ItemName.py index d4fb9496007f..3e6292cb67f3 100644 --- a/worlds/celeste64/Names/ItemName.py +++ b/worlds/celeste64/Names/ItemName.py @@ -15,3 +15,18 @@ air_dash = "Air Dash" skid_jump = "Skid Jump" climb = "Climb" + +# Checkpoint Items +checkpoint_1 = "Intro Checkpoint" +checkpoint_2 = "Granny Checkpoint" +checkpoint_3 = "South-East Tower Checkpoint" +checkpoint_4 = "Climb Sign Checkpoint" +checkpoint_5 = "Highway Checkpoint" +checkpoint_6 = "Highway Feather Checkpoint" +checkpoint_7 = "Feather Maze Checkpoint" +checkpoint_8 = "Double Dash House Checkpoint" +checkpoint_9 = "Badeline Tower Checkpoint" +checkpoint_10 = "Badeline Island Checkpoint" + +# Item used for logic definitions that are not possible with the given options +cannot_access = "CANNOT ACCESS" diff --git a/worlds/celeste64/Names/LocationName.py b/worlds/celeste64/Names/LocationName.py index 1b784f3875f1..ba39dc693a71 100644 --- a/worlds/celeste64/Names/LocationName.py +++ b/worlds/celeste64/Names/LocationName.py @@ -10,7 +10,7 @@ strawberry_9 = "South-West Dash Refills Strawberry" strawberry_10 = "South-East Tower Side Strawberry" strawberry_11 = "Girders Strawberry" -strawberry_12 = "North-East Tower Bottom Strawberry" +strawberry_12 = "Badeline Tower Bottom Strawberry" strawberry_13 = "Breakable Blocks Strawberry" strawberry_14 = "Feather Maze Strawberry" strawberry_15 = "Feather Chain Strawberry" @@ -18,7 +18,7 @@ strawberry_17 = "Double Dash Puzzle Strawberry" strawberry_18 = "Double Dash Spike Climb Strawberry" strawberry_19 = "Double Dash Spring Strawberry" -strawberry_20 = "North-East Tower Breakable Bottom Strawberry" +strawberry_20 = "Badeline Tower Breakable Bottom Strawberry" strawberry_21 = "Theo Tower Lower Cassette Strawberry" strawberry_22 = "Theo Tower Upper Cassette Strawberry" strawberry_23 = "South End of Bridge Cassette Strawberry" @@ -27,8 +27,8 @@ strawberry_26 = "North End of Bridge Cassette Strawberry" strawberry_27 = "Distant Feather Cassette Strawberry" strawberry_28 = "Feather Arches Cassette Strawberry" -strawberry_29 = "North-East Tower Cassette Strawberry" -strawberry_30 = "Badeline Cassette Strawberry" +strawberry_29 = "Badeline Tower Cassette Strawberry" +strawberry_30 = "Badeline Island Cassette Strawberry" # Friend Locations granny_1 = "Granny Conversation 1" @@ -51,3 +51,15 @@ # Car Locations car_1 = "Intro Car" car_2 = "Secret Car" + +# Checkpoint Locations +checkpoint_1 = "Intro Checkpoint" +checkpoint_2 = "Granny Checkpoint" +checkpoint_3 = "South-East Tower Checkpoint" +checkpoint_4 = "Climb Sign Checkpoint" +checkpoint_5 = "Highway Checkpoint" +checkpoint_6 = "Highway Feather Checkpoint" +checkpoint_7 = "Feather Maze Checkpoint" +checkpoint_8 = "Double Dash House Checkpoint" +checkpoint_9 = "Badeline Tower Checkpoint" +checkpoint_10 = "Badeline Island Checkpoint" diff --git a/worlds/celeste64/Names/RegionName.py b/worlds/celeste64/Names/RegionName.py new file mode 100644 index 000000000000..72a57d54a598 --- /dev/null +++ b/worlds/celeste64/Names/RegionName.py @@ -0,0 +1,13 @@ +# Level Base Regions +forsaken_city = "Forsaken City" + +# Forsaken City Regions +intro_islands = "Intro Islands" +granny_island = "Granny Island" +highway_island = "Highway Island" +nw_girders_island = "North-West Girders Island" +ne_feathers_island = "North-East Feathers Island" +se_house_island = "South-East House Island" +badeline_tower_lower = "Badeline Tower Lower" +badeline_tower_upper = "Badeline Tower Upper" +badeline_island = "Badeline Island" diff --git a/worlds/celeste64/Options.py b/worlds/celeste64/Options.py index 9a67e7d7d4f5..5a8dd7a8caa0 100644 --- a/worlds/celeste64/Options.py +++ b/worlds/celeste64/Options.py @@ -73,6 +73,12 @@ class Carsanity(Toggle): """ display_name = "Carsanity" +class Checkpointsanity(Toggle): + """ + Whether riding on cars grants location checks + """ + display_name = "Checkpointsanity" + class BadelineChaserSource(Choice): """ @@ -119,6 +125,7 @@ class BadelineChaserSpeed(Range): Friendsanity, Signsanity, Carsanity, + Checkpointsanity, ]), OptionGroup("Badeline Chasers", [ BadelineChaserSource, @@ -142,6 +149,7 @@ class Celeste64Options(PerGameCommonOptions): friendsanity: Friendsanity signsanity: Signsanity carsanity: Carsanity + checkpointsanity: Checkpointsanity badeline_chaser_source: BadelineChaserSource badeline_chaser_frequency: BadelineChaserFrequency diff --git a/worlds/celeste64/Regions.py b/worlds/celeste64/Regions.py index 6f01c873a4f9..4463cef5fbd8 100644 --- a/worlds/celeste64/Regions.py +++ b/worlds/celeste64/Regions.py @@ -1,11 +1,22 @@ from typing import Dict, List, NamedTuple +from .Names import RegionName class Celeste64RegionData(NamedTuple): connecting_regions: List[str] = [] region_data_table: Dict[str, Celeste64RegionData] = { - "Menu": Celeste64RegionData(["Forsaken City"]), - "Forsaken City": Celeste64RegionData(), + "Menu": Celeste64RegionData([RegionName.forsaken_city]), + RegionName.forsaken_city: Celeste64RegionData([RegionName.intro_islands]), + + RegionName.intro_islands: Celeste64RegionData([RegionName.granny_island]), + RegionName.granny_island: Celeste64RegionData([RegionName.highway_island, RegionName.nw_girders_island, RegionName.badeline_tower_lower, RegionName.se_house_island]), + RegionName.highway_island: Celeste64RegionData([RegionName.granny_island, RegionName.ne_feathers_island, RegionName.nw_girders_island]), + RegionName.nw_girders_island: Celeste64RegionData([RegionName.highway_island]), + RegionName.ne_feathers_island: Celeste64RegionData([RegionName.se_house_island, RegionName.highway_island, RegionName.badeline_tower_lower, RegionName.badeline_tower_upper]), + RegionName.se_house_island: Celeste64RegionData([RegionName.ne_feathers_island, RegionName.granny_island, RegionName.badeline_tower_lower]), + RegionName.badeline_tower_lower: Celeste64RegionData([RegionName.se_house_island, RegionName.ne_feathers_island, RegionName.granny_island, RegionName.badeline_tower_upper]), + RegionName.badeline_tower_upper: Celeste64RegionData([RegionName.badeline_island, RegionName.badeline_tower_lower, RegionName.se_house_island, RegionName.ne_feathers_island, RegionName.granny_island]), + RegionName.badeline_island: Celeste64RegionData([RegionName.badeline_tower_upper, RegionName.granny_island, RegionName.highway_island]), } diff --git a/worlds/celeste64/Rules.py b/worlds/celeste64/Rules.py index ebb47cca3093..1227105ec529 100644 --- a/worlds/celeste64/Rules.py +++ b/worlds/celeste64/Rules.py @@ -1,23 +1,27 @@ -from typing import Dict, List +from typing import Dict, List, Tuple, Callable -from BaseClasses import CollectionState +from BaseClasses import CollectionState, Region from worlds.generic.Rules import set_rule from . import Celeste64World -from .Names import ItemName, LocationName +from .Names import ItemName, LocationName, RegionName def set_rules(world: Celeste64World): if world.options.logic_difficulty == "standard": if world.options.move_shuffle: world.active_logic_mapping = location_standard_moves_logic + world.active_region_logic_mapping = region_standard_moves_logic else: world.active_logic_mapping = location_standard_logic + world.active_region_logic_mapping = region_standard_logic else: if world.options.move_shuffle: world.active_logic_mapping = location_hard_moves_logic + world.active_region_logic_mapping = region_hard_moves_logic else: world.active_logic_mapping = location_hard_logic + world.active_region_logic_mapping = region_hard_logic for location in world.multiworld.get_locations(world.player): set_rule(location, lambda state, location=location: location_rule(state, world, location.name)) @@ -320,6 +324,58 @@ def set_rules(world: Celeste64World): [ItemName.breakables, ItemName.air_dash]], } +# TODO: Region Connection Logic +region_standard_logic: Dict[Tuple[str], List[List[str]]] = { + (RegionName.intro_islands, RegionName.granny_island): [[]], # Free + + (RegionName.granny_island, RegionName.highway_island): [[ItemName.dash_refill]], + (RegionName.granny_island, RegionName.nw_girders_island): [[ItemName.traffic_block]], + (RegionName.granny_island, RegionName.badeline_tower_lower): [[ItemName.dash_refill]], + (RegionName.granny_island, RegionName.se_house_island): [[ItemName.double_dash_refill]], + + (RegionName.highway_island, RegionName.granny_island): [[ItemName.traffic_block], [ItemName.dash_refill]], + (RegionName.highway_island, RegionName.ne_feathers_island): [[ItemName.feather]], + (RegionName.highway_island, RegionName.nw_girders_island): [[ItemName.cannot_access]], + + (RegionName.nw_girders_island, RegionName.highway_island): [[ItemName.traffic_block]], + + (RegionName.ne_feathers_island, RegionName.se_house_island): [[]], # Free + (RegionName.ne_feathers_island, RegionName.highway_island): [[ItemName.feather]], + (RegionName.ne_feathers_island, RegionName.badeline_tower_lower): [[ItemName.feather]], + (RegionName.ne_feathers_island, RegionName.badeline_tower_upper): [[ItemName.feather]], + + (RegionName.se_house_island, RegionName.ne_feathers_island): [[]], # Free + (RegionName.se_house_island, RegionName.granny_island): [[ItemName.traffic_block, ItemName.double_dash_refill]], + (RegionName.se_house_island, RegionName.badeline_tower_lower): [[ItemName.double_dash_refill]], + + (RegionName.badeline_tower_lower, RegionName.se_house_island): [[ItemName.cannot_access]], + (RegionName.badeline_tower_lower, RegionName.ne_feathers_island): [[ItemName.breakables, ItemName.feather]], + (RegionName.badeline_tower_lower, RegionName.granny_island): [[ItemName.cannot_access]], + (RegionName.badeline_tower_lower, RegionName.badeline_tower_upper): [[ItemName.cannot_access]], + + (RegionName.badeline_tower_upper, RegionName.badeline_island): [[]], + (RegionName.badeline_tower_upper, RegionName.badeline_tower_lower): [[]], # Free + (RegionName.badeline_tower_upper, RegionName.se_house_island): [[]], # Free + (RegionName.badeline_tower_upper, RegionName.ne_feathers_island): [[]], # Free + (RegionName.badeline_tower_upper, RegionName.granny_island): [[ItemName.dash_refill]], + + (RegionName.badeline_island, RegionName.badeline_tower_upper): [[]], # Free + (RegionName.badeline_island, RegionName.granny_island): [[]], # Free + (RegionName.badeline_island, RegionName.highway_island): [[]], # Free +} + +region_standard_moves_logic: Dict[Tuple[str], List[List[str]]] = { + +} + +region_hard_logic: Dict[Tuple[str], List[List[str]]] = { + +} + +region_hard_moves_logic: Dict[Tuple[str], List[List[str]]] = { + +} + def location_rule(state: CollectionState, world: Celeste64World, loc: str) -> bool: @@ -332,6 +388,18 @@ def location_rule(state: CollectionState, world: Celeste64World, loc: str) -> bo return False +def region_connection_rule(state: CollectionState, world: Celeste64World, source_reg: str, dest_reg: str) -> bool: + connection: Tuple[str] = (source_reg, dest_reg) + + if connection not in world.active_region_logic_mapping: + return True + + for possible_access in world.active_region_logic_mapping[connection]: + if state.has_all(possible_access, world.player): + return True + + return False + def goal_rule(state: CollectionState, world: Celeste64World) -> bool: if not state.has(ItemName.strawberry, world.player, world.strawberries_required): return False @@ -341,3 +409,14 @@ def goal_rule(state: CollectionState, world: Celeste64World) -> bool: return True return False + +def connect_region(world: Celeste64World, region: Region, dest_regions: List[str]): + + rules: Dict[str, Callable[[CollectionState], bool]] = {} + + for dest_region in dest_regions: + rules[dest_region] = lambda state, dest_region=dest_region: region_connection_rule(state, world, region.name, dest_region) + + region.add_exits(dest_regions, rules) + + pass diff --git a/worlds/celeste64/__init__.py b/worlds/celeste64/__init__.py index 7786e381230a..5d08c07404a2 100644 --- a/worlds/celeste64/__init__.py +++ b/worlds/celeste64/__init__.py @@ -1,11 +1,13 @@ from copy import deepcopy -from typing import Dict, List +from typing import Dict, List, Tuple from BaseClasses import ItemClassification, Location, Region, Tutorial from worlds.AutoWorld import WebWorld, World -from .Items import Celeste64Item, unlockable_item_data_table, move_item_data_table, item_data_table, item_table +from .Items import Celeste64Item, unlockable_item_data_table, move_item_data_table, item_data_table,\ + checkpoint_item_data_table, item_table from .Locations import Celeste64Location, strawberry_location_data_table, friend_location_data_table,\ - sign_location_data_table, car_location_data_table, location_table + sign_location_data_table, car_location_data_table, checkpoint_location_data_table,\ + location_table from .Names import ItemName, LocationName from .Options import Celeste64Options, celeste_64_option_groups @@ -42,6 +44,7 @@ class Celeste64World(World): # Instance Data strawberries_required: int active_logic_mapping: Dict[str, List[List[str]]] + active_region_logic_mapping: Dict[Tuple[str], List[List[str]]] goal_logic_mapping: Dict[str, List[List[str]]] @@ -96,6 +99,16 @@ def create_items(self) -> None: for name in move_items_for_itempool if name not in self.options.start_inventory] + if self.options.checkpointsanity: + location_count += 10 + item_pool += [self.create_item(name) + for name in checkpoint_item_data_table.keys() + if name not in self.options.start_inventory] + else: + for item_name in checkpoint_item_data_table.keys(): + checkpoint_loc: Location = self.multiworld.get_location(item_name, self.player) + checkpoint_loc.place_locked_item(self.create_item(item_name)) + real_total_strawberries: int = min(self.options.total_strawberries.value, location_count - len(item_pool)) self.strawberries_required = int(real_total_strawberries * (self.options.strawberries_required_percentage / 100)) @@ -140,7 +153,13 @@ def create_regions(self) -> None: if location_data.region == region_name }, Celeste64Location) - region.add_exits(region_data_table[region_name].connecting_regions) + region.add_locations({ + location_name: location_data.address for location_name, location_data in checkpoint_location_data_table.items() + if location_data.region == region_name + }, Celeste64Location) + + from .Rules import connect_region + connect_region(self, region, region_data_table[region_name].connecting_regions) def get_filler_item_name(self) -> str: From 1092abcdef534f9ff3393dd750a7eab7dfcfe6b7 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Sun, 12 Jan 2025 02:58:16 -0500 Subject: [PATCH 02/22] Checkpointsanity tweaks --- worlds/celeste64/Names/ItemName.py | 4 ++-- worlds/celeste64/Names/LocationName.py | 4 ++-- worlds/celeste64/Names/RegionName.py | 2 +- worlds/celeste64/__init__.py | 1 + 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/worlds/celeste64/Names/ItemName.py b/worlds/celeste64/Names/ItemName.py index 3e6292cb67f3..b4c02115cbba 100644 --- a/worlds/celeste64/Names/ItemName.py +++ b/worlds/celeste64/Names/ItemName.py @@ -21,8 +21,8 @@ checkpoint_2 = "Granny Checkpoint" checkpoint_3 = "South-East Tower Checkpoint" checkpoint_4 = "Climb Sign Checkpoint" -checkpoint_5 = "Highway Checkpoint" -checkpoint_6 = "Highway Feather Checkpoint" +checkpoint_5 = "Freeway Checkpoint" +checkpoint_6 = "Freeway Feather Checkpoint" checkpoint_7 = "Feather Maze Checkpoint" checkpoint_8 = "Double Dash House Checkpoint" checkpoint_9 = "Badeline Tower Checkpoint" diff --git a/worlds/celeste64/Names/LocationName.py b/worlds/celeste64/Names/LocationName.py index ba39dc693a71..784d2049cfa2 100644 --- a/worlds/celeste64/Names/LocationName.py +++ b/worlds/celeste64/Names/LocationName.py @@ -57,8 +57,8 @@ checkpoint_2 = "Granny Checkpoint" checkpoint_3 = "South-East Tower Checkpoint" checkpoint_4 = "Climb Sign Checkpoint" -checkpoint_5 = "Highway Checkpoint" -checkpoint_6 = "Highway Feather Checkpoint" +checkpoint_5 = "Freeway Checkpoint" +checkpoint_6 = "Freeway Feather Checkpoint" checkpoint_7 = "Feather Maze Checkpoint" checkpoint_8 = "Double Dash House Checkpoint" checkpoint_9 = "Badeline Tower Checkpoint" diff --git a/worlds/celeste64/Names/RegionName.py b/worlds/celeste64/Names/RegionName.py index 72a57d54a598..ddb07a5bdaeb 100644 --- a/worlds/celeste64/Names/RegionName.py +++ b/worlds/celeste64/Names/RegionName.py @@ -4,7 +4,7 @@ # Forsaken City Regions intro_islands = "Intro Islands" granny_island = "Granny Island" -highway_island = "Highway Island" +highway_island = "Freeway Island" nw_girders_island = "North-West Girders Island" ne_feathers_island = "North-East Feathers Island" se_house_island = "South-East House Island" diff --git a/worlds/celeste64/__init__.py b/worlds/celeste64/__init__.py index 5d08c07404a2..7969d6505fed 100644 --- a/worlds/celeste64/__init__.py +++ b/worlds/celeste64/__init__.py @@ -180,6 +180,7 @@ def fill_slot_data(self): "friendsanity": self.options.friendsanity.value, "signsanity": self.options.signsanity.value, "carsanity": self.options.carsanity.value, + "checkpointsanity": self.options.checkpointsanity.value, "badeline_chaser_source": self.options.badeline_chaser_source.value, "badeline_chaser_frequency": self.options.badeline_chaser_frequency.value, "badeline_chaser_speed": self.options.badeline_chaser_speed.value, From 83e9bf9c75f74c1edba937ad1bed210a36ab7b27 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Sun, 12 Jan 2025 14:14:21 -0500 Subject: [PATCH 03/22] Hair Color Shuffle --- worlds/celeste64/Options.py | 223 ++++++++++++++++++++++++++++++++++- worlds/celeste64/__init__.py | 13 +- 2 files changed, 234 insertions(+), 2 deletions(-) diff --git a/worlds/celeste64/Options.py b/worlds/celeste64/Options.py index 5a8dd7a8caa0..ec43875d9193 100644 --- a/worlds/celeste64/Options.py +++ b/worlds/celeste64/Options.py @@ -1,6 +1,8 @@ from dataclasses import dataclass +import random -from Options import Choice, Range, Toggle, DeathLink, OptionGroup, PerGameCommonOptions +from Options import Choice, TextChoice, Range, Toggle, DeathLink, OptionGroup, PerGameCommonOptions, OptionError +from worlds.AutoWorld import World class DeathLinkAmnesty(Range): @@ -80,6 +82,159 @@ class Checkpointsanity(Toggle): display_name = "Checkpointsanity" +class MadelineOneDashHairColor(TextChoice): + """ + What color Madeline's hair is when she has one dash + + The `any_color` option will choose a fully random color + + A custom color entry must be a 6-character RGB hex color code + """ + display_name = "Madeline One Dash Hair Color" + option_strawberry = 0xDB2C00 + option_empty = 0x6EC0FF + option_double = 0xFA91FF + option_golden = 0xF2D450 + option_baddy = 0x9B3FB5 + option_fire_red = 0xFF0000 + option_maroon = 0x800000 + option_salmon = 0xFF3A65 + option_orange = 0xD86E0A + option_lime_green = 0x8DF920 + option_bright_green = 0x0DAF05 + option_forest_green = 0x132818 + option_royal_blue = 0x0036BF + option_brown = 0xB78726 + option_black = 0x000000 + option_white = 0xFFFFFF + option_grey = 0x808080 + option_any_color = -1 + default = option_strawberry + + @classmethod + def from_text(cls, text: str) -> Choice: + text = text.lower() + if text == "random": + choice_list = list(cls.name_lookup) + choice_list.remove(-1) + return cls(random.choice(choice_list)) + return super().from_text(text) + +class MadelineTwoDashHairColor(TextChoice): + """ + What color Madeline's hair is when she has two dashes + + The `any_color` option will choose a fully random color + + A custom color entry must be a 6-character RGB hex color code + """ + display_name = "Madeline Two Dash Hair Color" + option_strawberry = 0xDB2C00 + option_empty = 0x6EC0FF + option_double = 0xFA91FF + option_golden = 0xF2D450 + option_baddy = 0x9B3FB5 + option_fire_red = 0xFF0000 + option_maroon = 0x800000 + option_salmon = 0xFF3A65 + option_orange = 0xD86E0A + option_lime_green = 0x8DF920 + option_bright_green = 0x0DAF05 + option_forest_green = 0x132818 + option_royal_blue = 0x0036BF + option_brown = 0xB78726 + option_black = 0x000000 + option_white = 0xFFFFFF + option_grey = 0x808080 + option_any_color = -1 + default = option_double + + @classmethod + def from_text(cls, text: str) -> Choice: + text = text.lower() + if text == "random": + choice_list = list(cls.name_lookup) + choice_list.remove(-1) + return cls(random.choice(choice_list)) + return super().from_text(text) + +class MadelineNoDashHairColor(TextChoice): + """ + What color Madeline's hair is when she has no dashes + + The `any_color` option will choose a fully random color + + A custom color entry must be a 6-character RGB hex color code + """ + display_name = "Madeline No Dash Hair Color" + option_strawberry = 0xDB2C00 + option_empty = 0x6EC0FF + option_double = 0xFA91FF + option_golden = 0xF2D450 + option_baddy = 0x9B3FB5 + option_fire_red = 0xFF0000 + option_maroon = 0x800000 + option_salmon = 0xFF3A65 + option_orange = 0xD86E0A + option_lime_green = 0x8DF920 + option_bright_green = 0x0DAF05 + option_forest_green = 0x132818 + option_royal_blue = 0x0036BF + option_brown = 0xB78726 + option_black = 0x000000 + option_white = 0xFFFFFF + option_grey = 0x808080 + option_any_color = -1 + default = option_empty + + @classmethod + def from_text(cls, text: str) -> Choice: + text = text.lower() + if text == "random": + choice_list = list(cls.name_lookup) + choice_list.remove(-1) + return cls(random.choice(choice_list)) + return super().from_text(text) + +class MadelineFeatherHairColor(TextChoice): + """ + What color Madeline's hair is when she has a feather + + The `any_color` option will choose a fully random color + + A custom color entry must be a 6-character RGB hex color code + """ + display_name = "Madeline Feather Hair Color" + option_strawberry = 0xDB2C00 + option_empty = 0x6EC0FF + option_double = 0xFA91FF + option_golden = 0xF2D450 + option_baddy = 0x9B3FB5 + option_fire_red = 0xFF0000 + option_maroon = 0x800000 + option_salmon = 0xFF3A65 + option_orange = 0xD86E0A + option_lime_green = 0x8DF920 + option_bright_green = 0x0DAF05 + option_forest_green = 0x132818 + option_royal_blue = 0x0036BF + option_brown = 0xB78726 + option_black = 0x000000 + option_white = 0xFFFFFF + option_grey = 0x808080 + option_any_color = -1 + default = option_golden + + @classmethod + def from_text(cls, text: str) -> Choice: + text = text.lower() + if text == "random": + choice_list = list(cls.name_lookup) + choice_list.remove(-1) + return cls(random.choice(choice_list)) + return super().from_text(text) + + class BadelineChaserSource(Choice): """ What type of action causes more Badeline Chasers to start spawning @@ -127,6 +282,12 @@ class BadelineChaserSpeed(Range): Carsanity, Checkpointsanity, ]), + OptionGroup("Aesthetic Options", [ + MadelineOneDashHairColor, + MadelineTwoDashHairColor, + MadelineNoDashHairColor, + MadelineFeatherHairColor, + ]), OptionGroup("Badeline Chasers", [ BadelineChaserSource, BadelineChaserFrequency, @@ -151,6 +312,66 @@ class Celeste64Options(PerGameCommonOptions): carsanity: Carsanity checkpointsanity: Checkpointsanity + madeline_one_dash_hair_color: MadelineOneDashHairColor + madeline_two_dash_hair_color: MadelineTwoDashHairColor + madeline_no_dash_hair_color: MadelineNoDashHairColor + madeline_feather_hair_color: MadelineFeatherHairColor + badeline_chaser_source: BadelineChaserSource badeline_chaser_frequency: BadelineChaserFrequency badeline_chaser_speed: BadelineChaserSpeed + + +def resolve_options(world: World): + # One Dash Hair + if isinstance(world.options.madeline_one_dash_hair_color.value, str): + try: + world.madeline_one_dash_hair_color = int(world.options.madeline_one_dash_hair_color.value[:6], 16) + except ValueError: + raise OptionError(f"Invalid input for option `madeline_one_dash_hair_color`:" + f"{world.options.madeline_one_dash_hair_color.value} for " + f"{world.multiworld.get_player_name(world.player)}") + elif world.options.madeline_one_dash_hair_color.value == -1: + world.madeline_one_dash_hair_color = world.random.randint(0, 0xFFFFFF) + else: + world.madeline_one_dash_hair_color = world.options.madeline_one_dash_hair_color.value + + # Two Dash Hair + if isinstance(world.options.madeline_two_dash_hair_color.value, str): + try: + world.madeline_two_dash_hair_color = int(world.options.madeline_two_dash_hair_color.value[:6], 16) + except ValueError: + raise OptionError(f"Invalid input for option `madeline_two_dash_hair_color`:" + f"{world.options.madeline_two_dash_hair_color.value} for " + f"{world.multiworld.get_player_name(world.player)}") + elif world.options.madeline_two_dash_hair_color.value == -1: + world.madeline_two_dash_hair_color = world.random.randint(0, 0xFFFFFF) + else: + world.madeline_two_dash_hair_color = world.options.madeline_two_dash_hair_color.value + + # No Dash Hair + if isinstance(world.options.madeline_no_dash_hair_color.value, str): + try: + world.madeline_no_dash_hair_color = int(world.options.madeline_no_dash_hair_color.value[:6], 16) + except ValueError: + raise OptionError(f"Invalid input for option `madeline_no_dash_hair_color`:" + f"{world.options.madeline_no_dash_hair_color.value} for " + f"{world.multiworld.get_player_name(world.player)}") + elif world.options.madeline_no_dash_hair_color.value == -1: + world.madeline_no_dash_hair_color = world.random.randint(0, 0xFFFFFF) + else: + world.madeline_no_dash_hair_color = world.options.madeline_no_dash_hair_color.value + + # Feather Hair + if isinstance(world.options.madeline_feather_hair_color.value, str): + try: + world.madeline_feather_hair_color = int(world.options.madeline_feather_hair_color.value[:6], 16) + except ValueError: + raise OptionError(f"Invalid input for option `madeline_feather_hair_color`:" + f"{world.options.madeline_feather_hair_color.value} for " + f"{world.multiworld.get_player_name(world.player)}") + elif world.options.madeline_feather_hair_color.value == -1: + world.madeline_feather_hair_color = world.random.randint(0, 0xFFFFFF) + else: + world.madeline_feather_hair_color = world.options.madeline_feather_hair_color.value + diff --git a/worlds/celeste64/__init__.py b/worlds/celeste64/__init__.py index 7969d6505fed..aba4331f9617 100644 --- a/worlds/celeste64/__init__.py +++ b/worlds/celeste64/__init__.py @@ -9,7 +9,7 @@ sign_location_data_table, car_location_data_table, checkpoint_location_data_table,\ location_table from .Names import ItemName, LocationName -from .Options import Celeste64Options, celeste_64_option_groups +from .Options import Celeste64Options, celeste_64_option_groups, resolve_options class Celeste64WebWorld(WebWorld): @@ -47,6 +47,13 @@ class Celeste64World(World): active_region_logic_mapping: Dict[Tuple[str], List[List[str]]] goal_logic_mapping: Dict[str, List[List[str]]] + madeline_one_dash_hair_color: int + madeline_two_dash_hair_color: int + madeline_no_dash_hair_color: int + madeline_feather_hair_color: int + + def generate_early(self) -> None: + resolve_options(self) def create_item(self, name: str) -> Celeste64Item: # Only make required amount of strawberries be Progression @@ -181,6 +188,10 @@ def fill_slot_data(self): "signsanity": self.options.signsanity.value, "carsanity": self.options.carsanity.value, "checkpointsanity": self.options.checkpointsanity.value, + "madeline_one_dash_hair_color": self.madeline_one_dash_hair_color, + "madeline_two_dash_hair_color": self.madeline_two_dash_hair_color, + "madeline_no_dash_hair_color": self.madeline_no_dash_hair_color, + "madeline_feather_hair_color": self.madeline_feather_hair_color, "badeline_chaser_source": self.options.badeline_chaser_source.value, "badeline_chaser_frequency": self.options.badeline_chaser_frequency.value, "badeline_chaser_speed": self.options.badeline_chaser_speed.value, From 505724d1e67dda8a64c772eff92c139b90fd49a9 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Sun, 12 Jan 2025 18:24:51 -0500 Subject: [PATCH 04/22] Put locations in proper regions, and lock Badeline Checkpoint item/location --- worlds/celeste64/Locations.py | 114 +++++++++++++++++----------------- worlds/celeste64/Regions.py | 15 ++--- worlds/celeste64/__init__.py | 6 +- 3 files changed, 69 insertions(+), 66 deletions(-) diff --git a/worlds/celeste64/Locations.py b/worlds/celeste64/Locations.py index 88183873f311..0f38aeac7f5a 100644 --- a/worlds/celeste64/Locations.py +++ b/worlds/celeste64/Locations.py @@ -1,7 +1,7 @@ from typing import Dict, NamedTuple, Optional from BaseClasses import Location -from .Names import LocationName +from .Names import LocationName, RegionName celeste_64_base_id: int = 0xCA0000 @@ -18,74 +18,74 @@ class Celeste64LocationData(NamedTuple): # TODO: Move these locations to correct new regions strawberry_location_data_table: Dict[str, Celeste64LocationData] = { - LocationName.strawberry_1: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x00), - LocationName.strawberry_2: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x01), - LocationName.strawberry_3: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x02), - LocationName.strawberry_4: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x03), - LocationName.strawberry_5: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x04), - LocationName.strawberry_6: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x05), - LocationName.strawberry_7: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x06), - LocationName.strawberry_8: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x07), - LocationName.strawberry_9: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x08), - LocationName.strawberry_10: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x09), - LocationName.strawberry_11: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x0A), - LocationName.strawberry_12: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x0B), - LocationName.strawberry_13: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x0C), - LocationName.strawberry_14: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x0D), - LocationName.strawberry_15: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x0E), - LocationName.strawberry_16: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x0F), - LocationName.strawberry_17: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x10), - LocationName.strawberry_18: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x11), - LocationName.strawberry_19: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x12), - LocationName.strawberry_20: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x13), - LocationName.strawberry_21: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x14), - LocationName.strawberry_22: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x15), - LocationName.strawberry_23: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x16), - LocationName.strawberry_24: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x17), - LocationName.strawberry_25: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x18), - LocationName.strawberry_26: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x19), - LocationName.strawberry_27: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x1A), - LocationName.strawberry_28: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x1B), - LocationName.strawberry_29: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x1C), - LocationName.strawberry_30: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x1D), + LocationName.strawberry_1: Celeste64LocationData(RegionName.intro_islands, celeste_64_base_id + 0x00), + LocationName.strawberry_2: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x01), + LocationName.strawberry_3: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x02), + LocationName.strawberry_4: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x03), + LocationName.strawberry_5: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x04), + LocationName.strawberry_6: Celeste64LocationData(RegionName.highway_island, celeste_64_base_id + 0x05), + LocationName.strawberry_7: Celeste64LocationData(RegionName.highway_island, celeste_64_base_id + 0x06), + LocationName.strawberry_8: Celeste64LocationData(RegionName.nw_girders_island, celeste_64_base_id + 0x07), + LocationName.strawberry_9: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x08), + LocationName.strawberry_10: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x09), + LocationName.strawberry_11: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x0A), + LocationName.strawberry_12: Celeste64LocationData(RegionName.badeline_tower_lower, celeste_64_base_id + 0x0B), + LocationName.strawberry_13: Celeste64LocationData(RegionName.highway_island, celeste_64_base_id + 0x0C), + LocationName.strawberry_14: Celeste64LocationData(RegionName.ne_feathers_island, celeste_64_base_id + 0x0D), + LocationName.strawberry_15: Celeste64LocationData(RegionName.ne_feathers_island, celeste_64_base_id + 0x0E), + LocationName.strawberry_16: Celeste64LocationData(RegionName.ne_feathers_island, celeste_64_base_id + 0x0F), + LocationName.strawberry_17: Celeste64LocationData(RegionName.se_house_island, celeste_64_base_id + 0x10), + LocationName.strawberry_18: Celeste64LocationData(RegionName.se_house_island, celeste_64_base_id + 0x11), + LocationName.strawberry_19: Celeste64LocationData(RegionName.se_house_island, celeste_64_base_id + 0x12), + LocationName.strawberry_20: Celeste64LocationData(RegionName.badeline_tower_lower, celeste_64_base_id + 0x13), + LocationName.strawberry_21: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x14), + LocationName.strawberry_22: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x15), + LocationName.strawberry_23: Celeste64LocationData(RegionName.highway_island, celeste_64_base_id + 0x16), + LocationName.strawberry_24: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x17), + LocationName.strawberry_25: Celeste64LocationData(RegionName.se_house_island, celeste_64_base_id + 0x18), + LocationName.strawberry_26: Celeste64LocationData(RegionName.highway_island, celeste_64_base_id + 0x19), + LocationName.strawberry_27: Celeste64LocationData(RegionName.ne_feathers_island, celeste_64_base_id + 0x1A), + LocationName.strawberry_28: Celeste64LocationData(RegionName.ne_feathers_island, celeste_64_base_id + 0x1B), + LocationName.strawberry_29: Celeste64LocationData(RegionName.badeline_tower_upper, celeste_64_base_id + 0x1C), + LocationName.strawberry_30: Celeste64LocationData(RegionName.badeline_island, celeste_64_base_id + 0x1D), } friend_location_data_table: Dict[str, Celeste64LocationData] = { - LocationName.granny_1: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x00), - LocationName.granny_2: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x01), - LocationName.granny_3: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x02), - LocationName.theo_1: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x03), - LocationName.theo_2: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x04), - LocationName.theo_3: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x05), - LocationName.badeline_1: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x06), - LocationName.badeline_2: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x07), - LocationName.badeline_3: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x100 + 0x08), + LocationName.granny_1: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x100 + 0x00), + LocationName.granny_2: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x100 + 0x01), + LocationName.granny_3: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x100 + 0x02), + LocationName.theo_1: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x100 + 0x03), + LocationName.theo_2: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x100 + 0x04), + LocationName.theo_3: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x100 + 0x05), + LocationName.badeline_1: Celeste64LocationData(RegionName.badeline_island, celeste_64_base_id + 0x100 + 0x06), + LocationName.badeline_2: Celeste64LocationData(RegionName.badeline_island, celeste_64_base_id + 0x100 + 0x07), + LocationName.badeline_3: Celeste64LocationData(RegionName.badeline_island, celeste_64_base_id + 0x100 + 0x08), } sign_location_data_table: Dict[str, Celeste64LocationData] = { - LocationName.sign_1: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x200 + 0x00), - LocationName.sign_2: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x200 + 0x01), - LocationName.sign_3: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x200 + 0x02), - LocationName.sign_4: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x200 + 0x03), - LocationName.sign_5: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x200 + 0x04), + LocationName.sign_1: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x200 + 0x00), + LocationName.sign_2: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x200 + 0x01), + LocationName.sign_3: Celeste64LocationData(RegionName.highway_island, celeste_64_base_id + 0x200 + 0x02), + LocationName.sign_4: Celeste64LocationData(RegionName.se_house_island, celeste_64_base_id + 0x200 + 0x03), + LocationName.sign_5: Celeste64LocationData(RegionName.badeline_island, celeste_64_base_id + 0x200 + 0x04), } car_location_data_table: Dict[str, Celeste64LocationData] = { - LocationName.car_1: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x300 + 0x00), - LocationName.car_2: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x300 + 0x01), + LocationName.car_1: Celeste64LocationData(RegionName.intro_islands, celeste_64_base_id + 0x300 + 0x00), + LocationName.car_2: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x300 + 0x01), } checkpoint_location_data_table: Dict[str, Celeste64LocationData] = { - LocationName.checkpoint_1: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x00), - LocationName.checkpoint_2: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x01), - LocationName.checkpoint_3: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x02), - LocationName.checkpoint_4: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x03), - LocationName.checkpoint_5: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x04), - LocationName.checkpoint_6: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x05), - LocationName.checkpoint_7: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x06), - LocationName.checkpoint_8: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x07), - LocationName.checkpoint_9: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x08), - LocationName.checkpoint_10: Celeste64LocationData("Forsaken City", celeste_64_base_id + 0x400 + 0x09), + LocationName.checkpoint_1: Celeste64LocationData(RegionName.intro_islands, celeste_64_base_id + 0x400 + 0x00), + LocationName.checkpoint_2: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x400 + 0x01), + LocationName.checkpoint_3: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x400 + 0x02), + LocationName.checkpoint_4: Celeste64LocationData(RegionName.granny_island, celeste_64_base_id + 0x400 + 0x03), + LocationName.checkpoint_5: Celeste64LocationData(RegionName.highway_island, celeste_64_base_id + 0x400 + 0x04), + LocationName.checkpoint_6: Celeste64LocationData(RegionName.highway_island, celeste_64_base_id + 0x400 + 0x05), + LocationName.checkpoint_7: Celeste64LocationData(RegionName.ne_feathers_island, celeste_64_base_id + 0x400 + 0x06), + LocationName.checkpoint_8: Celeste64LocationData(RegionName.se_house_island, celeste_64_base_id + 0x400 + 0x07), + LocationName.checkpoint_9: Celeste64LocationData(RegionName.badeline_tower_upper, celeste_64_base_id + 0x400 + 0x08), + LocationName.checkpoint_10: Celeste64LocationData(RegionName.badeline_island, celeste_64_base_id + 0x400 + 0x09), } location_data_table: Dict[str, Celeste64LocationData] = {**strawberry_location_data_table, diff --git a/worlds/celeste64/Regions.py b/worlds/celeste64/Regions.py index 4463cef5fbd8..863d4c2a8ed0 100644 --- a/worlds/celeste64/Regions.py +++ b/worlds/celeste64/Regions.py @@ -8,15 +8,16 @@ class Celeste64RegionData(NamedTuple): region_data_table: Dict[str, Celeste64RegionData] = { "Menu": Celeste64RegionData([RegionName.forsaken_city]), + RegionName.forsaken_city: Celeste64RegionData([RegionName.intro_islands]), - RegionName.intro_islands: Celeste64RegionData([RegionName.granny_island]), - RegionName.granny_island: Celeste64RegionData([RegionName.highway_island, RegionName.nw_girders_island, RegionName.badeline_tower_lower, RegionName.se_house_island]), - RegionName.highway_island: Celeste64RegionData([RegionName.granny_island, RegionName.ne_feathers_island, RegionName.nw_girders_island]), - RegionName.nw_girders_island: Celeste64RegionData([RegionName.highway_island]), - RegionName.ne_feathers_island: Celeste64RegionData([RegionName.se_house_island, RegionName.highway_island, RegionName.badeline_tower_lower, RegionName.badeline_tower_upper]), - RegionName.se_house_island: Celeste64RegionData([RegionName.ne_feathers_island, RegionName.granny_island, RegionName.badeline_tower_lower]), + RegionName.intro_islands: Celeste64RegionData([RegionName.granny_island]), + RegionName.granny_island: Celeste64RegionData([RegionName.highway_island, RegionName.nw_girders_island, RegionName.badeline_tower_lower, RegionName.se_house_island]), + RegionName.highway_island: Celeste64RegionData([RegionName.granny_island, RegionName.ne_feathers_island, RegionName.nw_girders_island]), + RegionName.nw_girders_island: Celeste64RegionData([RegionName.highway_island]), + RegionName.ne_feathers_island: Celeste64RegionData([RegionName.se_house_island, RegionName.highway_island, RegionName.badeline_tower_lower, RegionName.badeline_tower_upper]), + RegionName.se_house_island: Celeste64RegionData([RegionName.ne_feathers_island, RegionName.granny_island, RegionName.badeline_tower_lower]), RegionName.badeline_tower_lower: Celeste64RegionData([RegionName.se_house_island, RegionName.ne_feathers_island, RegionName.granny_island, RegionName.badeline_tower_upper]), RegionName.badeline_tower_upper: Celeste64RegionData([RegionName.badeline_island, RegionName.badeline_tower_lower, RegionName.se_house_island, RegionName.ne_feathers_island, RegionName.granny_island]), - RegionName.badeline_island: Celeste64RegionData([RegionName.badeline_tower_upper, RegionName.granny_island, RegionName.highway_island]), + RegionName.badeline_island: Celeste64RegionData([RegionName.badeline_tower_upper, RegionName.granny_island, RegionName.highway_island]), } diff --git a/worlds/celeste64/__init__.py b/worlds/celeste64/__init__.py index aba4331f9617..6fba199cec24 100644 --- a/worlds/celeste64/__init__.py +++ b/worlds/celeste64/__init__.py @@ -107,10 +107,12 @@ def create_items(self) -> None: if name not in self.options.start_inventory] if self.options.checkpointsanity: - location_count += 10 + location_count += 9 + goal_checkpoint_loc: Location = self.multiworld.get_location(LocationName.checkpoint_10, self.player) + goal_checkpoint_loc.place_locked_item(self.create_item(ItemName.checkpoint_10)) item_pool += [self.create_item(name) for name in checkpoint_item_data_table.keys() - if name not in self.options.start_inventory] + if name not in self.options.start_inventory and name != ItemName.checkpoint_10] else: for item_name in checkpoint_item_data_table.keys(): checkpoint_loc: Location = self.multiworld.get_location(item_name, self.player) From 50b14f9d18f307478588a30d3dd611978d7fab9c Mon Sep 17 00:00:00 2001 From: PoryGone Date: Mon, 13 Jan 2025 02:46:26 -0500 Subject: [PATCH 05/22] Finished Region Logic --- worlds/celeste64/Locations.py | 1 - worlds/celeste64/Rules.py | 300 ++++++++++++++-------------------- 2 files changed, 122 insertions(+), 179 deletions(-) diff --git a/worlds/celeste64/Locations.py b/worlds/celeste64/Locations.py index 0f38aeac7f5a..9e202eca1203 100644 --- a/worlds/celeste64/Locations.py +++ b/worlds/celeste64/Locations.py @@ -15,7 +15,6 @@ class Celeste64LocationData(NamedTuple): region: str address: Optional[int] = None -# TODO: Move these locations to correct new regions strawberry_location_data_table: Dict[str, Celeste64LocationData] = { LocationName.strawberry_1: Celeste64LocationData(RegionName.intro_islands, celeste_64_base_id + 0x00), diff --git a/worlds/celeste64/Rules.py b/worlds/celeste64/Rules.py index 1227105ec529..561f1eb6b129 100644 --- a/worlds/celeste64/Rules.py +++ b/worlds/celeste64/Rules.py @@ -53,62 +53,32 @@ def set_rules(world: Celeste64World): location_standard_logic: Dict[str, List[List[str]]] = { LocationName.strawberry_4: [[ItemName.traffic_block, ItemName.breakables]], - LocationName.strawberry_6: [[ItemName.dash_refill], - [ItemName.traffic_block]], - LocationName.strawberry_7: [[ItemName.dash_refill], - [ItemName.traffic_block]], - LocationName.strawberry_8: [[ItemName.traffic_block]], LocationName.strawberry_9: [[ItemName.dash_refill]], - LocationName.strawberry_11: [[ItemName.dash_refill], - [ItemName.traffic_block]], - LocationName.strawberry_12: [[ItemName.dash_refill, ItemName.double_dash_refill], - [ItemName.traffic_block, ItemName.double_dash_refill]], - LocationName.strawberry_13: [[ItemName.dash_refill, ItemName.breakables], - [ItemName.traffic_block, ItemName.breakables]], - LocationName.strawberry_14: [[ItemName.dash_refill, ItemName.feather], - [ItemName.traffic_block, ItemName.feather]], - LocationName.strawberry_15: [[ItemName.dash_refill, ItemName.feather], - [ItemName.traffic_block, ItemName.feather]], - LocationName.strawberry_16: [[ItemName.dash_refill, ItemName.feather], - [ItemName.traffic_block, ItemName.feather]], + LocationName.strawberry_13: [[ItemName.breakables]], + LocationName.strawberry_14: [[ItemName.feather]], + LocationName.strawberry_15: [[ItemName.feather]], + LocationName.strawberry_16: [[ItemName.feather]], LocationName.strawberry_17: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block]], - LocationName.strawberry_18: [[ItemName.dash_refill, ItemName.double_dash_refill], - [ItemName.traffic_block, ItemName.feather, ItemName.double_dash_refill]], - LocationName.strawberry_19: [[ItemName.dash_refill, ItemName.double_dash_refill, ItemName.spring], - [ItemName.traffic_block, ItemName.double_dash_refill, ItemName.feather, ItemName.spring]], - LocationName.strawberry_20: [[ItemName.dash_refill, ItemName.feather, ItemName.breakables], - [ItemName.traffic_block, ItemName.feather, ItemName.breakables]], + LocationName.strawberry_18: [[ItemName.double_dash_refill]], + LocationName.strawberry_19: [[ItemName.double_dash_refill, ItemName.spring]], + LocationName.strawberry_20: [[ItemName.feather, ItemName.breakables]], LocationName.strawberry_21: [[ItemName.cassette, ItemName.traffic_block, ItemName.breakables]], LocationName.strawberry_22: [[ItemName.cassette, ItemName.dash_refill, ItemName.breakables]], - LocationName.strawberry_23: [[ItemName.cassette, ItemName.dash_refill, ItemName.coin], - [ItemName.cassette, ItemName.traffic_block, ItemName.coin]], + LocationName.strawberry_23: [[ItemName.cassette, ItemName.coin]], LocationName.strawberry_24: [[ItemName.cassette, ItemName.dash_refill, ItemName.traffic_block]], - LocationName.strawberry_25: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill], - [ItemName.cassette, ItemName.traffic_block, ItemName.feather, ItemName.double_dash_refill]], - LocationName.strawberry_26: [[ItemName.cassette, ItemName.dash_refill], - [ItemName.cassette, ItemName.traffic_block]], - LocationName.strawberry_27: [[ItemName.cassette, ItemName.dash_refill, ItemName.feather, ItemName.coin], - [ItemName.cassette, ItemName.traffic_block, ItemName.feather, ItemName.coin]], - LocationName.strawberry_28: [[ItemName.cassette, ItemName.dash_refill, ItemName.feather, ItemName.coin], - [ItemName.cassette, ItemName.traffic_block, ItemName.feather, ItemName.coin]], - LocationName.strawberry_29: [[ItemName.cassette, ItemName.dash_refill, ItemName.feather, ItemName.coin]], - LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.spring, ItemName.breakables]], + LocationName.strawberry_25: [[ItemName.cassette, ItemName.double_dash_refill]], + LocationName.strawberry_26: [[ItemName.cassette]], + LocationName.strawberry_27: [[ItemName.cassette, ItemName.feather, ItemName.coin]], + LocationName.strawberry_28: [[ItemName.cassette, ItemName.feather, ItemName.coin]], + LocationName.strawberry_29: [[ItemName.cassette, ItemName.dash_refill, ItemName.coin]], + LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.spring, ItemName.breakables]], LocationName.theo_1: [[ItemName.traffic_block, ItemName.breakables]], LocationName.theo_2: [[ItemName.traffic_block, ItemName.breakables]], LocationName.theo_3: [[ItemName.traffic_block, ItemName.breakables]], - LocationName.badeline_1: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], - LocationName.badeline_2: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], - LocationName.badeline_3: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], LocationName.sign_2: [[ItemName.breakables]], - LocationName.sign_3: [[ItemName.dash_refill], - [ItemName.traffic_block]], - LocationName.sign_4: [[ItemName.dash_refill, ItemName.double_dash_refill], - [ItemName.dash_refill, ItemName.feather], - [ItemName.traffic_block, ItemName.feather]], - LocationName.sign_5: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], LocationName.car_2: [[ItemName.breakables]], } @@ -135,131 +105,53 @@ def set_rules(world: Celeste64World): } location_standard_moves_logic: Dict[str, List[List[str]]] = { - LocationName.strawberry_1: [[ItemName.ground_dash], - [ItemName.air_dash], - [ItemName.skid_jump], - [ItemName.climb]], - LocationName.strawberry_2: [[ItemName.ground_dash], - [ItemName.air_dash], - [ItemName.skid_jump], - [ItemName.climb]], LocationName.strawberry_3: [[ItemName.air_dash], [ItemName.skid_jump]], LocationName.strawberry_4: [[ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], LocationName.strawberry_5: [[ItemName.air_dash]], - LocationName.strawberry_6: [[ItemName.dash_refill, ItemName.air_dash], - [ItemName.traffic_block, ItemName.ground_dash], - [ItemName.traffic_block, ItemName.air_dash], - [ItemName.traffic_block, ItemName.skid_jump], - [ItemName.traffic_block, ItemName.climb]], - LocationName.strawberry_7: [[ItemName.dash_refill, ItemName.air_dash], - [ItemName.traffic_block, ItemName.ground_dash], - [ItemName.traffic_block, ItemName.air_dash], - [ItemName.traffic_block, ItemName.skid_jump], - [ItemName.traffic_block, ItemName.climb]], - LocationName.strawberry_8: [[ItemName.traffic_block, ItemName.ground_dash], - [ItemName.traffic_block, ItemName.air_dash], - [ItemName.traffic_block, ItemName.skid_jump], - [ItemName.traffic_block, ItemName.climb]], LocationName.strawberry_9: [[ItemName.dash_refill, ItemName.air_dash]], LocationName.strawberry_10: [[ItemName.climb]], - LocationName.strawberry_11: [[ItemName.dash_refill, ItemName.air_dash, ItemName.climb], - [ItemName.traffic_block, ItemName.climb]], - LocationName.strawberry_12: [[ItemName.dash_refill, ItemName.double_dash_refill, ItemName.air_dash], - [ItemName.traffic_block, ItemName.double_dash_refill, ItemName.air_dash]], - LocationName.strawberry_13: [[ItemName.dash_refill, ItemName.breakables, ItemName.air_dash], - [ItemName.traffic_block, ItemName.breakables, ItemName.ground_dash], - [ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], - LocationName.strawberry_14: [[ItemName.dash_refill, ItemName.feather, ItemName.air_dash], - [ItemName.traffic_block, ItemName.feather, ItemName.air_dash]], - LocationName.strawberry_15: [[ItemName.dash_refill, ItemName.feather, ItemName.air_dash, ItemName.climb], - [ItemName.traffic_block, ItemName.feather, ItemName.climb]], - LocationName.strawberry_16: [[ItemName.dash_refill, ItemName.feather, ItemName.air_dash], - [ItemName.traffic_block, ItemName.feather]], - LocationName.strawberry_17: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.ground_dash], - [ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.air_dash], - [ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.skid_jump], - [ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.climb]], - LocationName.strawberry_18: [[ItemName.dash_refill, ItemName.double_dash_refill, ItemName.air_dash, ItemName.climb], - [ItemName.traffic_block, ItemName.feather, ItemName.double_dash_refill, ItemName.air_dash, ItemName.climb]], - LocationName.strawberry_19: [[ItemName.dash_refill, ItemName.double_dash_refill, ItemName.spring, ItemName.air_dash], - [ItemName.traffic_block, ItemName.double_dash_refill, ItemName.feather, ItemName.spring, ItemName.air_dash]], - LocationName.strawberry_20: [[ItemName.dash_refill, ItemName.feather, ItemName.breakables, ItemName.air_dash], - [ItemName.traffic_block, ItemName.feather, ItemName.breakables, ItemName.air_dash]], + LocationName.strawberry_11: [[ItemName.air_dash, ItemName.climb]], + LocationName.strawberry_13: [[ItemName.breakables, ItemName.air_dash], + [ItemName.breakables, ItemName.ground_dash]], + LocationName.strawberry_14: [[ItemName.feather, ItemName.air_dash]], + LocationName.strawberry_15: [[ItemName.feather, ItemName.air_dash, ItemName.climb]], + LocationName.strawberry_16: [[ItemName.feather]], + LocationName.strawberry_17: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block]], + LocationName.strawberry_18: [[ItemName.double_dash_refill, ItemName.air_dash, ItemName.climb]], + LocationName.strawberry_19: [[ItemName.double_dash_refill, ItemName.spring, ItemName.air_dash, ItemName.skid_jump]], + LocationName.strawberry_20: [[ItemName.feather, ItemName.breakables, ItemName.air_dash]], LocationName.strawberry_21: [[ItemName.cassette, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], LocationName.strawberry_22: [[ItemName.cassette, ItemName.dash_refill, ItemName.breakables, ItemName.air_dash]], - LocationName.strawberry_23: [[ItemName.cassette, ItemName.dash_refill, ItemName.coin, ItemName.air_dash, ItemName.climb], - [ItemName.cassette, ItemName.traffic_block, ItemName.coin, ItemName.air_dash, ItemName.climb]], + LocationName.strawberry_23: [[ItemName.cassette, ItemName.coin, ItemName.air_dash, ItemName.climb]], LocationName.strawberry_24: [[ItemName.cassette, ItemName.dash_refill, ItemName.traffic_block, ItemName.air_dash]], - LocationName.strawberry_25: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.air_dash, ItemName.climb], - [ItemName.cassette, ItemName.traffic_block, ItemName.feather, ItemName.double_dash_refill, ItemName.air_dash, ItemName.climb]], - LocationName.strawberry_26: [[ItemName.cassette, ItemName.dash_refill, ItemName.air_dash, ItemName.climb], - [ItemName.cassette, ItemName.traffic_block, ItemName.air_dash, ItemName.climb]], - LocationName.strawberry_27: [[ItemName.cassette, ItemName.dash_refill, ItemName.feather, ItemName.coin, ItemName.air_dash], - [ItemName.cassette, ItemName.traffic_block, ItemName.feather, ItemName.coin, ItemName.air_dash]], - LocationName.strawberry_28: [[ItemName.cassette, ItemName.dash_refill, ItemName.feather, ItemName.coin, ItemName.air_dash, ItemName.climb], - [ItemName.cassette, ItemName.traffic_block, ItemName.feather, ItemName.coin, ItemName.air_dash, ItemName.climb]], - LocationName.strawberry_29: [[ItemName.cassette, ItemName.dash_refill, ItemName.feather, ItemName.coin, ItemName.air_dash, ItemName.skid_jump]], + LocationName.strawberry_25: [[ItemName.cassette, ItemName.double_dash_refill, ItemName.air_dash, ItemName.climb]], + LocationName.strawberry_26: [[ItemName.cassette, ItemName.air_dash, ItemName.climb]], + LocationName.strawberry_27: [[ItemName.cassette, ItemName.feather, ItemName.coin, ItemName.air_dash, ItemName.climb]], + LocationName.strawberry_28: [[ItemName.cassette, ItemName.feather, ItemName.coin, ItemName.air_dash, ItemName.climb]], + LocationName.strawberry_29: [[ItemName.cassette, ItemName.dash_refill, ItemName.coin, ItemName.air_dash, ItemName.skid_jump]], LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.spring, ItemName.breakables, ItemName.air_dash, ItemName.climb]], - LocationName.granny_1: [[ItemName.ground_dash], - [ItemName.air_dash], - [ItemName.skid_jump], - [ItemName.climb]], - LocationName.granny_2: [[ItemName.ground_dash], - [ItemName.air_dash], - [ItemName.skid_jump], - [ItemName.climb]], - LocationName.granny_3: [[ItemName.ground_dash], - [ItemName.air_dash], - [ItemName.skid_jump], - [ItemName.climb]], LocationName.theo_1: [[ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], LocationName.theo_2: [[ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], LocationName.theo_3: [[ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], - LocationName.badeline_1: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb]], - LocationName.badeline_2: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb]], - LocationName.badeline_3: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb]], - - LocationName.sign_1: [[ItemName.ground_dash], - [ItemName.air_dash], - [ItemName.skid_jump], - [ItemName.climb]], + LocationName.sign_2: [[ItemName.breakables, ItemName.ground_dash], [ItemName.breakables, ItemName.air_dash]], - LocationName.sign_3: [[ItemName.dash_refill, ItemName.air_dash], - [ItemName.traffic_block, ItemName.ground_dash], - [ItemName.traffic_block, ItemName.air_dash], - [ItemName.traffic_block, ItemName.skid_jump], - [ItemName.traffic_block, ItemName.climb]], - LocationName.sign_4: [[ItemName.dash_refill, ItemName.double_dash_refill, ItemName.air_dash], - [ItemName.dash_refill, ItemName.feather, ItemName.air_dash], - [ItemName.traffic_block, ItemName.feather, ItemName.ground_dash], - [ItemName.traffic_block, ItemName.feather, ItemName.air_dash], - [ItemName.traffic_block, ItemName.feather, ItemName.skid_jump], - [ItemName.traffic_block, ItemName.feather, ItemName.climb]], - LocationName.sign_5: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb]], LocationName.car_2: [[ItemName.breakables, ItemName.ground_dash], [ItemName.breakables, ItemName.air_dash]], } location_hard_moves_logic: Dict[str, List[List[str]]] = { - LocationName.strawberry_3: [[ItemName.air_dash], - [ItemName.skid_jump]], LocationName.strawberry_5: [[ItemName.ground_dash], [ItemName.air_dash]], - LocationName.strawberry_8: [[ItemName.traffic_block], - [ItemName.ground_dash, ItemName.air_dash]], LocationName.strawberry_10: [[ItemName.air_dash], [ItemName.climb]], LocationName.strawberry_11: [[ItemName.ground_dash], [ItemName.air_dash], [ItemName.skid_jump]], - LocationName.strawberry_12: [[ItemName.feather], - [ItemName.ground_dash], - [ItemName.air_dash]], LocationName.strawberry_13: [[ItemName.breakables, ItemName.ground_dash], [ItemName.breakables, ItemName.air_dash]], LocationName.strawberry_14: [[ItemName.feather, ItemName.air_dash], @@ -291,42 +183,18 @@ def set_rules(world: Celeste64World): [ItemName.cassette, ItemName.feather, ItemName.climb]], LocationName.strawberry_29: [[ItemName.cassette, ItemName.dash_refill, ItemName.air_dash, ItemName.skid_jump], [ItemName.cassette, ItemName.ground_dash, ItemName.air_dash]], - LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.ground_dash, ItemName.air_dash, ItemName.climb, ItemName.skid_jump], - [ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.feather, ItemName.air_dash, ItemName.climb, ItemName.skid_jump], - [ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.spring, ItemName.ground_dash, ItemName.air_dash, ItemName.climb], - [ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.spring, ItemName.feather, ItemName.air_dash, ItemName.climb]], - - LocationName.badeline_1: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb], - [ItemName.traffic_block, ItemName.air_dash, ItemName.skid_jump], - [ItemName.ground_dash, ItemName.air_dash, ItemName.skid_jump], - [ItemName.feather, ItemName.traffic_block, ItemName.air_dash], - [ItemName.traffic_block, ItemName.ground_dash, ItemName.air_dash]], - LocationName.badeline_2: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb], - [ItemName.traffic_block, ItemName.air_dash, ItemName.skid_jump], - [ItemName.ground_dash, ItemName.air_dash, ItemName.skid_jump], - [ItemName.feather, ItemName.traffic_block, ItemName.air_dash], - [ItemName.traffic_block, ItemName.ground_dash, ItemName.air_dash]], - LocationName.badeline_3: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb], - [ItemName.traffic_block, ItemName.air_dash, ItemName.skid_jump], - [ItemName.ground_dash, ItemName.air_dash, ItemName.skid_jump], - [ItemName.feather, ItemName.traffic_block, ItemName.air_dash], - [ItemName.traffic_block, ItemName.ground_dash, ItemName.air_dash]], + LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb, ItemName.skid_jump], + [ItemName.cassette, ItemName.dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.spring, ItemName.air_dash, ItemName.climb]], LocationName.sign_2: [[ItemName.breakables, ItemName.ground_dash], [ItemName.breakables, ItemName.air_dash]], - LocationName.sign_5: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb], - [ItemName.traffic_block, ItemName.air_dash, ItemName.skid_jump], - [ItemName.ground_dash, ItemName.air_dash, ItemName.skid_jump], - [ItemName.feather, ItemName.traffic_block, ItemName.air_dash], - [ItemName.traffic_block, ItemName.ground_dash, ItemName.air_dash]], LocationName.car_2: [[ItemName.breakables, ItemName.ground_dash], [ItemName.breakables, ItemName.air_dash]], } -# TODO: Region Connection Logic region_standard_logic: Dict[Tuple[str], List[List[str]]] = { - (RegionName.intro_islands, RegionName.granny_island): [[]], # Free + (RegionName.intro_islands, RegionName.granny_island): [[]], (RegionName.granny_island, RegionName.highway_island): [[ItemName.dash_refill]], (RegionName.granny_island, RegionName.nw_girders_island): [[ItemName.traffic_block]], @@ -339,12 +207,12 @@ def set_rules(world: Celeste64World): (RegionName.nw_girders_island, RegionName.highway_island): [[ItemName.traffic_block]], - (RegionName.ne_feathers_island, RegionName.se_house_island): [[]], # Free + (RegionName.ne_feathers_island, RegionName.se_house_island): [[]], (RegionName.ne_feathers_island, RegionName.highway_island): [[ItemName.feather]], (RegionName.ne_feathers_island, RegionName.badeline_tower_lower): [[ItemName.feather]], (RegionName.ne_feathers_island, RegionName.badeline_tower_upper): [[ItemName.feather]], - (RegionName.se_house_island, RegionName.ne_feathers_island): [[]], # Free + (RegionName.se_house_island, RegionName.ne_feathers_island): [[]], (RegionName.se_house_island, RegionName.granny_island): [[ItemName.traffic_block, ItemName.double_dash_refill]], (RegionName.se_house_island, RegionName.badeline_tower_lower): [[ItemName.double_dash_refill]], @@ -353,27 +221,103 @@ def set_rules(world: Celeste64World): (RegionName.badeline_tower_lower, RegionName.granny_island): [[ItemName.cannot_access]], (RegionName.badeline_tower_lower, RegionName.badeline_tower_upper): [[ItemName.cannot_access]], - (RegionName.badeline_tower_upper, RegionName.badeline_island): [[]], - (RegionName.badeline_tower_upper, RegionName.badeline_tower_lower): [[]], # Free - (RegionName.badeline_tower_upper, RegionName.se_house_island): [[]], # Free - (RegionName.badeline_tower_upper, RegionName.ne_feathers_island): [[]], # Free + (RegionName.badeline_tower_upper, RegionName.badeline_island): [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], + (RegionName.badeline_tower_upper, RegionName.badeline_tower_lower): [[]], + (RegionName.badeline_tower_upper, RegionName.se_house_island): [[]], + (RegionName.badeline_tower_upper, RegionName.ne_feathers_island): [[]], (RegionName.badeline_tower_upper, RegionName.granny_island): [[ItemName.dash_refill]], - (RegionName.badeline_island, RegionName.badeline_tower_upper): [[]], # Free - (RegionName.badeline_island, RegionName.granny_island): [[]], # Free - (RegionName.badeline_island, RegionName.highway_island): [[]], # Free + (RegionName.badeline_island, RegionName.badeline_tower_upper): [[]], + (RegionName.badeline_island, RegionName.granny_island): [[]], + (RegionName.badeline_island, RegionName.highway_island): [[]], } -region_standard_moves_logic: Dict[Tuple[str], List[List[str]]] = { - +region_hard_logic: Dict[Tuple[str], List[List[str]]] = { + # No Items are required for region access with these options. } -region_hard_logic: Dict[Tuple[str], List[List[str]]] = { +region_standard_moves_logic: Dict[Tuple[str], List[List[str]]] = { + (RegionName.intro_islands, RegionName.granny_island): [[ItemName.ground_dash], + [ItemName.air_dash], + [ItemName.skid_jump], + [ItemName.climb]], + (RegionName.granny_island, RegionName.highway_island): [[ItemName.air_dash, ItemName.dash_refill]], + (RegionName.granny_island, RegionName.nw_girders_island): [[ItemName.traffic_block]], + (RegionName.granny_island, RegionName.badeline_tower_lower): [[ItemName.air_dash, ItemName.climb, ItemName.dash_refill]], + (RegionName.granny_island, RegionName.se_house_island): [[ItemName.air_dash, ItemName.climb, ItemName.double_dash_refill]], + + (RegionName.highway_island, RegionName.granny_island): [[ItemName.traffic_block], [ItemName.air_dash, ItemName.dash_refill]], + (RegionName.highway_island, RegionName.ne_feathers_island): [[ItemName.feather]], + (RegionName.highway_island, RegionName.nw_girders_island): [[ItemName.cannot_access]], + + (RegionName.nw_girders_island, RegionName.highway_island): [[ItemName.traffic_block]], + + (RegionName.ne_feathers_island, RegionName.se_house_island): [[]], + (RegionName.ne_feathers_island, RegionName.highway_island): [[ItemName.feather]], + (RegionName.ne_feathers_island, RegionName.badeline_tower_lower): [[ItemName.feather]], + (RegionName.ne_feathers_island, RegionName.badeline_tower_upper): [[ItemName.climb, ItemName.air_dash, ItemName.feather]], + + (RegionName.se_house_island, RegionName.ne_feathers_island): [[]], + (RegionName.se_house_island, RegionName.granny_island): [[ItemName.air_dash, ItemName.traffic_block, ItemName.double_dash_refill]], + (RegionName.se_house_island, RegionName.badeline_tower_lower): [[ItemName.air_dash, ItemName.double_dash_refill]], + + (RegionName.badeline_tower_lower, RegionName.se_house_island): [[ItemName.cannot_access]], + (RegionName.badeline_tower_lower, RegionName.ne_feathers_island): [[ItemName.air_dash, ItemName.breakables, ItemName.feather]], + (RegionName.badeline_tower_lower, RegionName.granny_island): [[ItemName.cannot_access]], + (RegionName.badeline_tower_lower, RegionName.badeline_tower_upper): [[ItemName.cannot_access]], + + (RegionName.badeline_tower_upper, RegionName.badeline_island): [[ItemName.air_dash, ItemName.climb, ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], + (RegionName.badeline_tower_upper, RegionName.badeline_tower_lower): [[]], + (RegionName.badeline_tower_upper, RegionName.se_house_island): [[ItemName.air_dash], [ItemName.ground_dash]], + (RegionName.badeline_tower_upper, RegionName.ne_feathers_island): [[ItemName.air_dash], [ItemName.ground_dash]], + (RegionName.badeline_tower_upper, RegionName.granny_island): [[ItemName.dash_refill]], + + (RegionName.badeline_island, RegionName.badeline_tower_upper): [[ItemName.air_dash], [ItemName.ground_dash]], + (RegionName.badeline_island, RegionName.granny_island): [[]], + (RegionName.badeline_island, RegionName.highway_island): [[]], } region_hard_moves_logic: Dict[Tuple[str], List[List[str]]] = { + (RegionName.intro_islands, RegionName.granny_island): [[]], + (RegionName.granny_island, RegionName.highway_island): [[]], + (RegionName.granny_island, RegionName.nw_girders_island): [[ItemName.traffic_block]], + (RegionName.granny_island, RegionName.badeline_tower_lower): [[ItemName.air_dash], [ItemName.ground_dash]], + (RegionName.granny_island, RegionName.se_house_island): [[ItemName.air_dash, ItemName.double_dash_refill], [ItemName.ground_dash]], + + (RegionName.highway_island, RegionName.granny_island): [[]], + (RegionName.highway_island, RegionName.ne_feathers_island): [], + (RegionName.highway_island, RegionName.nw_girders_island): [[ItemName.air_dash, ItemName.ground_dash]], + + (RegionName.nw_girders_island, RegionName.highway_island): [[ItemName.traffic_block], [ItemName.air_dash, ItemName.ground_dash]], + + (RegionName.ne_feathers_island, RegionName.se_house_island): [[]], + (RegionName.ne_feathers_island, RegionName.highway_island): [[ItemName.feather], [ItemName.air_dash], [ItemName.ground_dash], [ItemName.skid_jump]], + (RegionName.ne_feathers_island, RegionName.badeline_tower_lower): [[ItemName.feather], [ItemName.air_dash], [ItemName.ground_dash]], + (RegionName.ne_feathers_island, RegionName.badeline_tower_upper): [[ItemName.feather]], + + (RegionName.se_house_island, RegionName.ne_feathers_island): [[]], + (RegionName.se_house_island, RegionName.granny_island): [[ItemName.traffic_block]], + (RegionName.se_house_island, RegionName.badeline_tower_lower): [[ItemName.air_dash], [ItemName.ground_dash]], + + (RegionName.badeline_tower_lower, RegionName.se_house_island): [[]], + (RegionName.badeline_tower_lower, RegionName.ne_feathers_island): [[]], + (RegionName.badeline_tower_lower, RegionName.granny_island): [[]], + (RegionName.badeline_tower_lower, RegionName.badeline_tower_upper): [[]], + + (RegionName.badeline_tower_upper, RegionName.badeline_island): [[ItemName.air_dash, ItemName.climb, ItemName.feather, ItemName.traffic_block], + [ItemName.air_dash, ItemName.climb, ItemName.feather, ItemName.skid_jump], + [ItemName.air_dash, ItemName.climb, ItemName.ground_dash, ItemName.traffic_block], + [ItemName.air_dash, ItemName.climb, ItemName.ground_dash, ItemName.skid_jump]], + (RegionName.badeline_tower_upper, RegionName.badeline_tower_lower): [[]], + (RegionName.badeline_tower_upper, RegionName.se_house_island): [[]], + (RegionName.badeline_tower_upper, RegionName.ne_feathers_island): [[]], + (RegionName.badeline_tower_upper, RegionName.granny_island): [[]], + + (RegionName.badeline_island, RegionName.badeline_tower_upper): [[ItemName.air_dash], [ItemName.ground_dash]], + (RegionName.badeline_island, RegionName.granny_island): [[]], + (RegionName.badeline_island, RegionName.highway_island): [[]], } From efcae67b301f79db0ed1044336641e2eeb56d191 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Mon, 13 Jan 2025 02:55:16 -0500 Subject: [PATCH 06/22] Refactor goal handling --- worlds/celeste64/Rules.py | 36 ++---------------------------------- worlds/celeste64/__init__.py | 1 - 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/worlds/celeste64/Rules.py b/worlds/celeste64/Rules.py index 561f1eb6b129..cfbce687628e 100644 --- a/worlds/celeste64/Rules.py +++ b/worlds/celeste64/Rules.py @@ -26,29 +26,9 @@ def set_rules(world: Celeste64World): for location in world.multiworld.get_locations(world.player): set_rule(location, lambda state, location=location: location_rule(state, world, location.name)) - if world.options.logic_difficulty == "standard": - if world.options.move_shuffle: - world.goal_logic_mapping = goal_standard_moves_logic - else: - world.goal_logic_mapping = goal_standard_logic - else: - if world.options.move_shuffle: - world.goal_logic_mapping = goal_hard_moves_logic - else: - world.goal_logic_mapping = goal_hard_logic - # Completion condition. - world.multiworld.completion_condition[world.player] = lambda state: goal_rule(state, world) - - -goal_standard_logic: List[List[str]] = [[ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.double_dash_refill]] -goal_hard_logic: List[List[str]] = [[]] -goal_standard_moves_logic: List[List[str]] = [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb]] -goal_hard_moves_logic: List[List[str]] = [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb], - [ItemName.traffic_block, ItemName.air_dash, ItemName.skid_jump], - [ItemName.ground_dash, ItemName.air_dash, ItemName.skid_jump], - [ItemName.feather, ItemName.traffic_block, ItemName.air_dash], - [ItemName.traffic_block, ItemName.ground_dash, ItemName.air_dash]] + goal_region: Region = world.multiworld.get_region(RegionName.badeline_island, world.player) + world.multiworld.completion_condition[world.player] = lambda state: state.can_reach(goal_region) location_standard_logic: Dict[str, List[List[str]]] = { @@ -322,7 +302,6 @@ def set_rules(world: Celeste64World): def location_rule(state: CollectionState, world: Celeste64World, loc: str) -> bool: - if loc not in world.active_logic_mapping: return True @@ -344,18 +323,7 @@ def region_connection_rule(state: CollectionState, world: Celeste64World, source return False -def goal_rule(state: CollectionState, world: Celeste64World) -> bool: - if not state.has(ItemName.strawberry, world.player, world.strawberries_required): - return False - - for possible_access in world.goal_logic_mapping: - if state.has_all(possible_access, world.player): - return True - - return False - def connect_region(world: Celeste64World, region: Region, dest_regions: List[str]): - rules: Dict[str, Callable[[CollectionState], bool]] = {} for dest_region in dest_regions: diff --git a/worlds/celeste64/__init__.py b/worlds/celeste64/__init__.py index 6fba199cec24..5c86abd9f348 100644 --- a/worlds/celeste64/__init__.py +++ b/worlds/celeste64/__init__.py @@ -45,7 +45,6 @@ class Celeste64World(World): strawberries_required: int active_logic_mapping: Dict[str, List[List[str]]] active_region_logic_mapping: Dict[Tuple[str], List[List[str]]] - goal_logic_mapping: Dict[str, List[List[str]]] madeline_one_dash_hair_color: int madeline_two_dash_hair_color: int From deff88282958fd1bcf74d37564339550bef5121c Mon Sep 17 00:00:00 2001 From: PoryGone Date: Mon, 13 Jan 2025 03:04:43 -0500 Subject: [PATCH 07/22] Rerefactor goal condition --- worlds/celeste64/Rules.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/worlds/celeste64/Rules.py b/worlds/celeste64/Rules.py index cfbce687628e..0873e5d87b21 100644 --- a/worlds/celeste64/Rules.py +++ b/worlds/celeste64/Rules.py @@ -27,9 +27,7 @@ def set_rules(world: Celeste64World): set_rule(location, lambda state, location=location: location_rule(state, world, location.name)) # Completion condition. - goal_region: Region = world.multiworld.get_region(RegionName.badeline_island, world.player) - world.multiworld.completion_condition[world.player] = lambda state: state.can_reach(goal_region) - + world.multiworld.completion_condition[world.player] = lambda state: goal_rule(state, world) location_standard_logic: Dict[str, List[List[str]]] = { LocationName.strawberry_4: [[ItemName.traffic_block, ItemName.breakables]], @@ -173,6 +171,7 @@ def set_rules(world: Celeste64World): [ItemName.breakables, ItemName.air_dash]], } + region_standard_logic: Dict[Tuple[str], List[List[str]]] = { (RegionName.intro_islands, RegionName.granny_island): [[]], @@ -323,6 +322,13 @@ def region_connection_rule(state: CollectionState, world: Celeste64World, source return False +def goal_rule(state: CollectionState, world: Celeste64World) -> bool: + if not state.has(ItemName.strawberry, world.player, world.strawberries_required): + return False + + goal_region: Region = world.multiworld.get_region(RegionName.badeline_island, world.player) + return state.can_reach(goal_region) + def connect_region(world: Celeste64World, region: Region, dest_regions: List[str]): rules: Dict[str, Callable[[CollectionState], bool]] = {} From 79063d6ac6d870f0ce72d2c651632f480246388f Mon Sep 17 00:00:00 2001 From: PoryGone Date: Mon, 13 Jan 2025 03:29:38 -0500 Subject: [PATCH 08/22] Checkpoint connections and last cleanup --- worlds/celeste64/Regions.py | 2 +- worlds/celeste64/Rules.py | 60 +++++++++++++++++-------------------- 2 files changed, 28 insertions(+), 34 deletions(-) diff --git a/worlds/celeste64/Regions.py b/worlds/celeste64/Regions.py index 863d4c2a8ed0..7db683bbb925 100644 --- a/worlds/celeste64/Regions.py +++ b/worlds/celeste64/Regions.py @@ -9,7 +9,7 @@ class Celeste64RegionData(NamedTuple): region_data_table: Dict[str, Celeste64RegionData] = { "Menu": Celeste64RegionData([RegionName.forsaken_city]), - RegionName.forsaken_city: Celeste64RegionData([RegionName.intro_islands]), + RegionName.forsaken_city: Celeste64RegionData([RegionName.intro_islands, RegionName.granny_island, RegionName.highway_island, RegionName.ne_feathers_island, RegionName.se_house_island, RegionName.badeline_tower_upper, RegionName.badeline_island]), RegionName.intro_islands: Celeste64RegionData([RegionName.granny_island]), RegionName.granny_island: Celeste64RegionData([RegionName.highway_island, RegionName.nw_girders_island, RegionName.badeline_tower_lower, RegionName.se_house_island]), diff --git a/worlds/celeste64/Rules.py b/worlds/celeste64/Rules.py index 0873e5d87b21..e38722ac0a35 100644 --- a/worlds/celeste64/Rules.py +++ b/worlds/celeste64/Rules.py @@ -173,7 +173,12 @@ def set_rules(world: Celeste64World): region_standard_logic: Dict[Tuple[str], List[List[str]]] = { - (RegionName.intro_islands, RegionName.granny_island): [[]], + (RegionName.forsaken_city, RegionName.granny_island): [[ItemName.checkpoint_2], [ItemName.checkpoint_3], [ItemName.checkpoint_4]], + (RegionName.forsaken_city, RegionName.highway_island): [[ItemName.checkpoint_5], [ItemName.checkpoint_6]], + (RegionName.forsaken_city, RegionName.ne_feathers_island): [[ItemName.checkpoint_7]], + (RegionName.forsaken_city, RegionName.se_house_island): [[ItemName.checkpoint_8]], + (RegionName.forsaken_city, RegionName.badeline_tower_upper): [[ItemName.checkpoint_9]], + (RegionName.forsaken_city, RegionName.badeline_island): [[ItemName.checkpoint_10]], (RegionName.granny_island, RegionName.highway_island): [[ItemName.dash_refill]], (RegionName.granny_island, RegionName.nw_girders_island): [[ItemName.traffic_block]], @@ -186,12 +191,10 @@ def set_rules(world: Celeste64World): (RegionName.nw_girders_island, RegionName.highway_island): [[ItemName.traffic_block]], - (RegionName.ne_feathers_island, RegionName.se_house_island): [[]], (RegionName.ne_feathers_island, RegionName.highway_island): [[ItemName.feather]], (RegionName.ne_feathers_island, RegionName.badeline_tower_lower): [[ItemName.feather]], (RegionName.ne_feathers_island, RegionName.badeline_tower_upper): [[ItemName.feather]], - (RegionName.se_house_island, RegionName.ne_feathers_island): [[]], (RegionName.se_house_island, RegionName.granny_island): [[ItemName.traffic_block, ItemName.double_dash_refill]], (RegionName.se_house_island, RegionName.badeline_tower_lower): [[ItemName.double_dash_refill]], @@ -201,21 +204,28 @@ def set_rules(world: Celeste64World): (RegionName.badeline_tower_lower, RegionName.badeline_tower_upper): [[ItemName.cannot_access]], (RegionName.badeline_tower_upper, RegionName.badeline_island): [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], - (RegionName.badeline_tower_upper, RegionName.badeline_tower_lower): [[]], - (RegionName.badeline_tower_upper, RegionName.se_house_island): [[]], - (RegionName.badeline_tower_upper, RegionName.ne_feathers_island): [[]], (RegionName.badeline_tower_upper, RegionName.granny_island): [[ItemName.dash_refill]], - - (RegionName.badeline_island, RegionName.badeline_tower_upper): [[]], - (RegionName.badeline_island, RegionName.granny_island): [[]], - (RegionName.badeline_island, RegionName.highway_island): [[]], } region_hard_logic: Dict[Tuple[str], List[List[str]]] = { + (RegionName.forsaken_city, RegionName.granny_island): [[ItemName.checkpoint_2], [ItemName.checkpoint_3], [ItemName.checkpoint_4]], + (RegionName.forsaken_city, RegionName.highway_island): [[ItemName.checkpoint_5], [ItemName.checkpoint_6]], + (RegionName.forsaken_city, RegionName.ne_feathers_island): [[ItemName.checkpoint_7]], + (RegionName.forsaken_city, RegionName.se_house_island): [[ItemName.checkpoint_8]], + (RegionName.forsaken_city, RegionName.badeline_tower_upper): [[ItemName.checkpoint_9]], + (RegionName.forsaken_city, RegionName.badeline_island): [[ItemName.checkpoint_10]], + # No Items are required for region access with these options. } region_standard_moves_logic: Dict[Tuple[str], List[List[str]]] = { + (RegionName.forsaken_city, RegionName.granny_island): [[ItemName.checkpoint_2], [ItemName.checkpoint_3], [ItemName.checkpoint_4]], + (RegionName.forsaken_city, RegionName.highway_island): [[ItemName.checkpoint_5], [ItemName.checkpoint_6]], + (RegionName.forsaken_city, RegionName.ne_feathers_island): [[ItemName.checkpoint_7]], + (RegionName.forsaken_city, RegionName.se_house_island): [[ItemName.checkpoint_8]], + (RegionName.forsaken_city, RegionName.badeline_tower_upper): [[ItemName.checkpoint_9]], + (RegionName.forsaken_city, RegionName.badeline_island): [[ItemName.checkpoint_10]], + (RegionName.intro_islands, RegionName.granny_island): [[ItemName.ground_dash], [ItemName.air_dash], [ItemName.skid_jump], @@ -232,12 +242,10 @@ def set_rules(world: Celeste64World): (RegionName.nw_girders_island, RegionName.highway_island): [[ItemName.traffic_block]], - (RegionName.ne_feathers_island, RegionName.se_house_island): [[]], (RegionName.ne_feathers_island, RegionName.highway_island): [[ItemName.feather]], (RegionName.ne_feathers_island, RegionName.badeline_tower_lower): [[ItemName.feather]], (RegionName.ne_feathers_island, RegionName.badeline_tower_upper): [[ItemName.climb, ItemName.air_dash, ItemName.feather]], - (RegionName.se_house_island, RegionName.ne_feathers_island): [[]], (RegionName.se_house_island, RegionName.granny_island): [[ItemName.air_dash, ItemName.traffic_block, ItemName.double_dash_refill]], (RegionName.se_house_island, RegionName.badeline_tower_lower): [[ItemName.air_dash, ItemName.double_dash_refill]], @@ -247,56 +255,42 @@ def set_rules(world: Celeste64World): (RegionName.badeline_tower_lower, RegionName.badeline_tower_upper): [[ItemName.cannot_access]], (RegionName.badeline_tower_upper, RegionName.badeline_island): [[ItemName.air_dash, ItemName.climb, ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], - (RegionName.badeline_tower_upper, RegionName.badeline_tower_lower): [[]], (RegionName.badeline_tower_upper, RegionName.se_house_island): [[ItemName.air_dash], [ItemName.ground_dash]], (RegionName.badeline_tower_upper, RegionName.ne_feathers_island): [[ItemName.air_dash], [ItemName.ground_dash]], (RegionName.badeline_tower_upper, RegionName.granny_island): [[ItemName.dash_refill]], (RegionName.badeline_island, RegionName.badeline_tower_upper): [[ItemName.air_dash], [ItemName.ground_dash]], - (RegionName.badeline_island, RegionName.granny_island): [[]], - (RegionName.badeline_island, RegionName.highway_island): [[]], } region_hard_moves_logic: Dict[Tuple[str], List[List[str]]] = { - (RegionName.intro_islands, RegionName.granny_island): [[]], + (RegionName.forsaken_city, RegionName.granny_island): [[ItemName.checkpoint_2], [ItemName.checkpoint_3], [ItemName.checkpoint_4]], + (RegionName.forsaken_city, RegionName.highway_island): [[ItemName.checkpoint_5], [ItemName.checkpoint_6]], + (RegionName.forsaken_city, RegionName.ne_feathers_island): [[ItemName.checkpoint_7]], + (RegionName.forsaken_city, RegionName.se_house_island): [[ItemName.checkpoint_8]], + (RegionName.forsaken_city, RegionName.badeline_tower_upper): [[ItemName.checkpoint_9]], + (RegionName.forsaken_city, RegionName.badeline_island): [[ItemName.checkpoint_10]], - (RegionName.granny_island, RegionName.highway_island): [[]], (RegionName.granny_island, RegionName.nw_girders_island): [[ItemName.traffic_block]], (RegionName.granny_island, RegionName.badeline_tower_lower): [[ItemName.air_dash], [ItemName.ground_dash]], (RegionName.granny_island, RegionName.se_house_island): [[ItemName.air_dash, ItemName.double_dash_refill], [ItemName.ground_dash]], - (RegionName.highway_island, RegionName.granny_island): [[]], - (RegionName.highway_island, RegionName.ne_feathers_island): [], (RegionName.highway_island, RegionName.nw_girders_island): [[ItemName.air_dash, ItemName.ground_dash]], (RegionName.nw_girders_island, RegionName.highway_island): [[ItemName.traffic_block], [ItemName.air_dash, ItemName.ground_dash]], - (RegionName.ne_feathers_island, RegionName.se_house_island): [[]], (RegionName.ne_feathers_island, RegionName.highway_island): [[ItemName.feather], [ItemName.air_dash], [ItemName.ground_dash], [ItemName.skid_jump]], (RegionName.ne_feathers_island, RegionName.badeline_tower_lower): [[ItemName.feather], [ItemName.air_dash], [ItemName.ground_dash]], (RegionName.ne_feathers_island, RegionName.badeline_tower_upper): [[ItemName.feather]], - (RegionName.se_house_island, RegionName.ne_feathers_island): [[]], (RegionName.se_house_island, RegionName.granny_island): [[ItemName.traffic_block]], (RegionName.se_house_island, RegionName.badeline_tower_lower): [[ItemName.air_dash], [ItemName.ground_dash]], - (RegionName.badeline_tower_lower, RegionName.se_house_island): [[]], - (RegionName.badeline_tower_lower, RegionName.ne_feathers_island): [[]], - (RegionName.badeline_tower_lower, RegionName.granny_island): [[]], - (RegionName.badeline_tower_lower, RegionName.badeline_tower_upper): [[]], - (RegionName.badeline_tower_upper, RegionName.badeline_island): [[ItemName.air_dash, ItemName.climb, ItemName.feather, ItemName.traffic_block], [ItemName.air_dash, ItemName.climb, ItemName.feather, ItemName.skid_jump], [ItemName.air_dash, ItemName.climb, ItemName.ground_dash, ItemName.traffic_block], [ItemName.air_dash, ItemName.climb, ItemName.ground_dash, ItemName.skid_jump]], - (RegionName.badeline_tower_upper, RegionName.badeline_tower_lower): [[]], - (RegionName.badeline_tower_upper, RegionName.se_house_island): [[]], - (RegionName.badeline_tower_upper, RegionName.ne_feathers_island): [[]], - (RegionName.badeline_tower_upper, RegionName.granny_island): [[]], - + (RegionName.badeline_island, RegionName.badeline_tower_upper): [[ItemName.air_dash], [ItemName.ground_dash]], - (RegionName.badeline_island, RegionName.granny_island): [[]], - (RegionName.badeline_island, RegionName.highway_island): [[]], } From 6a84b9e37cfa8025ea19d177a7790cd534367b3d Mon Sep 17 00:00:00 2001 From: PoryGone Date: Fri, 17 Jan 2025 19:15:21 -0500 Subject: [PATCH 09/22] move_shuffle on and move_shuffle off + start with all moves can just share logic --- worlds/celeste64/Rules.py | 115 ++--------------------------------- worlds/celeste64/__init__.py | 3 + 2 files changed, 7 insertions(+), 111 deletions(-) diff --git a/worlds/celeste64/Rules.py b/worlds/celeste64/Rules.py index e38722ac0a35..cb28f2fc91c0 100644 --- a/worlds/celeste64/Rules.py +++ b/worlds/celeste64/Rules.py @@ -9,19 +9,11 @@ def set_rules(world: Celeste64World): if world.options.logic_difficulty == "standard": - if world.options.move_shuffle: - world.active_logic_mapping = location_standard_moves_logic - world.active_region_logic_mapping = region_standard_moves_logic - else: - world.active_logic_mapping = location_standard_logic - world.active_region_logic_mapping = region_standard_logic + world.active_logic_mapping = location_standard_moves_logic + world.active_region_logic_mapping = region_standard_moves_logic else: - if world.options.move_shuffle: - world.active_logic_mapping = location_hard_moves_logic - world.active_region_logic_mapping = region_hard_moves_logic - else: - world.active_logic_mapping = location_hard_logic - world.active_region_logic_mapping = region_hard_logic + world.active_logic_mapping = location_hard_moves_logic + world.active_region_logic_mapping = region_hard_moves_logic for location in world.multiworld.get_locations(world.player): set_rule(location, lambda state, location=location: location_rule(state, world, location.name)) @@ -29,59 +21,6 @@ def set_rules(world: Celeste64World): # Completion condition. world.multiworld.completion_condition[world.player] = lambda state: goal_rule(state, world) -location_standard_logic: Dict[str, List[List[str]]] = { - LocationName.strawberry_4: [[ItemName.traffic_block, ItemName.breakables]], - LocationName.strawberry_9: [[ItemName.dash_refill]], - LocationName.strawberry_13: [[ItemName.breakables]], - LocationName.strawberry_14: [[ItemName.feather]], - LocationName.strawberry_15: [[ItemName.feather]], - LocationName.strawberry_16: [[ItemName.feather]], - LocationName.strawberry_17: [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block]], - LocationName.strawberry_18: [[ItemName.double_dash_refill]], - LocationName.strawberry_19: [[ItemName.double_dash_refill, ItemName.spring]], - LocationName.strawberry_20: [[ItemName.feather, ItemName.breakables]], - - LocationName.strawberry_21: [[ItemName.cassette, ItemName.traffic_block, ItemName.breakables]], - LocationName.strawberry_22: [[ItemName.cassette, ItemName.dash_refill, ItemName.breakables]], - LocationName.strawberry_23: [[ItemName.cassette, ItemName.coin]], - LocationName.strawberry_24: [[ItemName.cassette, ItemName.dash_refill, ItemName.traffic_block]], - LocationName.strawberry_25: [[ItemName.cassette, ItemName.double_dash_refill]], - LocationName.strawberry_26: [[ItemName.cassette]], - LocationName.strawberry_27: [[ItemName.cassette, ItemName.feather, ItemName.coin]], - LocationName.strawberry_28: [[ItemName.cassette, ItemName.feather, ItemName.coin]], - LocationName.strawberry_29: [[ItemName.cassette, ItemName.dash_refill, ItemName.coin]], - LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.spring, ItemName.breakables]], - - LocationName.theo_1: [[ItemName.traffic_block, ItemName.breakables]], - LocationName.theo_2: [[ItemName.traffic_block, ItemName.breakables]], - LocationName.theo_3: [[ItemName.traffic_block, ItemName.breakables]], - - LocationName.sign_2: [[ItemName.breakables]], - - LocationName.car_2: [[ItemName.breakables]], -} - -location_hard_logic: Dict[str, List[List[str]]] = { - LocationName.strawberry_13: [[ItemName.breakables]], - LocationName.strawberry_17: [[ItemName.double_dash_refill, ItemName.traffic_block]], - LocationName.strawberry_20: [[ItemName.breakables]], - - LocationName.strawberry_21: [[ItemName.cassette, ItemName.traffic_block, ItemName.breakables]], - LocationName.strawberry_22: [[ItemName.cassette]], - LocationName.strawberry_23: [[ItemName.cassette, ItemName.coin]], - LocationName.strawberry_24: [[ItemName.cassette]], - LocationName.strawberry_25: [[ItemName.cassette, ItemName.double_dash_refill]], - LocationName.strawberry_26: [[ItemName.cassette]], - LocationName.strawberry_27: [[ItemName.cassette]], - LocationName.strawberry_28: [[ItemName.cassette, ItemName.feather]], - LocationName.strawberry_29: [[ItemName.cassette]], - LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.breakables]], - - LocationName.sign_2: [[ItemName.breakables]], - - LocationName.car_2: [[ItemName.breakables]], -} - location_standard_moves_logic: Dict[str, List[List[str]]] = { LocationName.strawberry_3: [[ItemName.air_dash], [ItemName.skid_jump]], @@ -172,52 +111,6 @@ def set_rules(world: Celeste64World): } -region_standard_logic: Dict[Tuple[str], List[List[str]]] = { - (RegionName.forsaken_city, RegionName.granny_island): [[ItemName.checkpoint_2], [ItemName.checkpoint_3], [ItemName.checkpoint_4]], - (RegionName.forsaken_city, RegionName.highway_island): [[ItemName.checkpoint_5], [ItemName.checkpoint_6]], - (RegionName.forsaken_city, RegionName.ne_feathers_island): [[ItemName.checkpoint_7]], - (RegionName.forsaken_city, RegionName.se_house_island): [[ItemName.checkpoint_8]], - (RegionName.forsaken_city, RegionName.badeline_tower_upper): [[ItemName.checkpoint_9]], - (RegionName.forsaken_city, RegionName.badeline_island): [[ItemName.checkpoint_10]], - - (RegionName.granny_island, RegionName.highway_island): [[ItemName.dash_refill]], - (RegionName.granny_island, RegionName.nw_girders_island): [[ItemName.traffic_block]], - (RegionName.granny_island, RegionName.badeline_tower_lower): [[ItemName.dash_refill]], - (RegionName.granny_island, RegionName.se_house_island): [[ItemName.double_dash_refill]], - - (RegionName.highway_island, RegionName.granny_island): [[ItemName.traffic_block], [ItemName.dash_refill]], - (RegionName.highway_island, RegionName.ne_feathers_island): [[ItemName.feather]], - (RegionName.highway_island, RegionName.nw_girders_island): [[ItemName.cannot_access]], - - (RegionName.nw_girders_island, RegionName.highway_island): [[ItemName.traffic_block]], - - (RegionName.ne_feathers_island, RegionName.highway_island): [[ItemName.feather]], - (RegionName.ne_feathers_island, RegionName.badeline_tower_lower): [[ItemName.feather]], - (RegionName.ne_feathers_island, RegionName.badeline_tower_upper): [[ItemName.feather]], - - (RegionName.se_house_island, RegionName.granny_island): [[ItemName.traffic_block, ItemName.double_dash_refill]], - (RegionName.se_house_island, RegionName.badeline_tower_lower): [[ItemName.double_dash_refill]], - - (RegionName.badeline_tower_lower, RegionName.se_house_island): [[ItemName.cannot_access]], - (RegionName.badeline_tower_lower, RegionName.ne_feathers_island): [[ItemName.breakables, ItemName.feather]], - (RegionName.badeline_tower_lower, RegionName.granny_island): [[ItemName.cannot_access]], - (RegionName.badeline_tower_lower, RegionName.badeline_tower_upper): [[ItemName.cannot_access]], - - (RegionName.badeline_tower_upper, RegionName.badeline_island): [[ItemName.double_dash_refill, ItemName.feather, ItemName.traffic_block, ItemName.breakables]], - (RegionName.badeline_tower_upper, RegionName.granny_island): [[ItemName.dash_refill]], -} - -region_hard_logic: Dict[Tuple[str], List[List[str]]] = { - (RegionName.forsaken_city, RegionName.granny_island): [[ItemName.checkpoint_2], [ItemName.checkpoint_3], [ItemName.checkpoint_4]], - (RegionName.forsaken_city, RegionName.highway_island): [[ItemName.checkpoint_5], [ItemName.checkpoint_6]], - (RegionName.forsaken_city, RegionName.ne_feathers_island): [[ItemName.checkpoint_7]], - (RegionName.forsaken_city, RegionName.se_house_island): [[ItemName.checkpoint_8]], - (RegionName.forsaken_city, RegionName.badeline_tower_upper): [[ItemName.checkpoint_9]], - (RegionName.forsaken_city, RegionName.badeline_island): [[ItemName.checkpoint_10]], - - # No Items are required for region access with these options. -} - region_standard_moves_logic: Dict[Tuple[str], List[List[str]]] = { (RegionName.forsaken_city, RegionName.granny_island): [[ItemName.checkpoint_2], [ItemName.checkpoint_3], [ItemName.checkpoint_4]], (RegionName.forsaken_city, RegionName.highway_island): [[ItemName.checkpoint_5], [ItemName.checkpoint_6]], diff --git a/worlds/celeste64/__init__.py b/worlds/celeste64/__init__.py index 5c86abd9f348..853391f6575c 100644 --- a/worlds/celeste64/__init__.py +++ b/worlds/celeste64/__init__.py @@ -104,6 +104,9 @@ def create_items(self) -> None: item_pool += [self.create_item(name) for name in move_items_for_itempool if name not in self.options.start_inventory] + else: + for start_move in move_item_data_table.keys(): + self.multiworld.push_precollected(self.create_item(start_move)) if self.options.checkpointsanity: location_count += 9 From fe9b3566608d42cfa3390d142263728dd5693325 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Sat, 18 Jan 2025 02:20:28 -0500 Subject: [PATCH 10/22] Logic tweaks --- worlds/celeste64/Rules.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/worlds/celeste64/Rules.py b/worlds/celeste64/Rules.py index cb28f2fc91c0..03f1fd32ca06 100644 --- a/worlds/celeste64/Rules.py +++ b/worlds/celeste64/Rules.py @@ -21,7 +21,12 @@ def set_rules(world: Celeste64World): # Completion condition. world.multiworld.completion_condition[world.player] = lambda state: goal_rule(state, world) + location_standard_moves_logic: Dict[str, List[List[str]]] = { + LocationName.strawberry_1: [[ItemName.ground_dash], + [ItemName.air_dash], + [ItemName.skid_jump], + [ItemName.climb]], LocationName.strawberry_3: [[ItemName.air_dash], [ItemName.skid_jump]], LocationName.strawberry_4: [[ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], @@ -57,8 +62,8 @@ def set_rules(world: Celeste64World): LocationName.sign_2: [[ItemName.breakables, ItemName.ground_dash], [ItemName.breakables, ItemName.air_dash]], - LocationName.car_2: [[ItemName.breakables, ItemName.ground_dash], - [ItemName.breakables, ItemName.air_dash]], + LocationName.car_2: [[ItemName.breakables, ItemName.ground_dash, ItemName.climb], + [ItemName.breakables, ItemName.air_dash, ItemName.climb]], } location_hard_moves_logic: Dict[str, List[List[str]]] = { @@ -100,8 +105,8 @@ def set_rules(world: Celeste64World): [ItemName.cassette, ItemName.feather, ItemName.climb]], LocationName.strawberry_29: [[ItemName.cassette, ItemName.dash_refill, ItemName.air_dash, ItemName.skid_jump], [ItemName.cassette, ItemName.ground_dash, ItemName.air_dash]], - LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb, ItemName.skid_jump], - [ItemName.cassette, ItemName.dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.spring, ItemName.air_dash, ItemName.climb]], + LocationName.strawberry_30: [[ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.air_dash, ItemName.climb, ItemName.skid_jump], + [ItemName.cassette, ItemName.dash_refill, ItemName.double_dash_refill, ItemName.traffic_block, ItemName.breakables, ItemName.spring, ItemName.air_dash, ItemName.climb]], LocationName.sign_2: [[ItemName.breakables, ItemName.ground_dash], [ItemName.breakables, ItemName.air_dash]], @@ -223,5 +228,3 @@ def connect_region(world: Celeste64World, region: Region, dest_regions: List[str rules[dest_region] = lambda state, dest_region=dest_region: region_connection_rule(state, world, region.name, dest_region) region.add_exits(dest_regions, rules) - - pass From e4af11205980e1398d4dab2a2bf0d9d50d15bd5d Mon Sep 17 00:00:00 2001 From: PoryGone Date: Sat, 18 Jan 2025 02:34:10 -0500 Subject: [PATCH 11/22] Changelog update --- worlds/celeste64/CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/worlds/celeste64/CHANGELOG.md b/worlds/celeste64/CHANGELOG.md index 5e562e17f443..a2e8e5cbd866 100644 --- a/worlds/celeste64/CHANGELOG.md +++ b/worlds/celeste64/CHANGELOG.md @@ -1,6 +1,25 @@ # Celeste 64 - Changelog +## v1.3 + +### Features: + +- New optional Location Checks + - Checkpointsanity +- Hair Color + - Allows for setting of Maddy's hair color in each of No Dash, One Dash, Two Dash, and Feather states +- Other Player Ghosts + - A game config option allows you to see ghosts of other Celeste 64 players in the world + +### Quality of Life: + +- Checkpoint Warping + - Received Checkpoint items allow for warping to their respective checkpoint + - These items are on their respective checkpoint location if Checkpointsanity is disabled + - Logic accounts for being able to warp to otherwise inaccessible areas + + ## v1.2 ### Features: From b48bbac72caeebe7ef1a83867f5e06c9247c3ca6 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Sat, 18 Jan 2025 03:32:55 -0500 Subject: [PATCH 12/22] Option doc fix --- worlds/celeste64/Options.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/worlds/celeste64/Options.py b/worlds/celeste64/Options.py index ec43875d9193..5044e6095a4f 100644 --- a/worlds/celeste64/Options.py +++ b/worlds/celeste64/Options.py @@ -20,7 +20,7 @@ class TotalStrawberries(Range): """ display_name = "Total Strawberries" range_start = 0 - range_end = 46 + range_end = 55 default = 20 class StrawberriesRequiredPercentage(Range): @@ -77,7 +77,9 @@ class Carsanity(Toggle): class Checkpointsanity(Toggle): """ - Whether riding on cars grants location checks + Whether activating Checkpoints grants location checks + + Activating this will also shuffle items into the pool which allow usage and warping to each Checkpoint """ display_name = "Checkpointsanity" From ebbdc0d65e17afb2626effd8d6ad47515db2b077 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Sun, 19 Jan 2025 00:44:05 -0500 Subject: [PATCH 13/22] Double Dash and Air Dash for Feather Maze Hard --- worlds/celeste64/Rules.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/worlds/celeste64/Rules.py b/worlds/celeste64/Rules.py index 03f1fd32ca06..bca213b7e297 100644 --- a/worlds/celeste64/Rules.py +++ b/worlds/celeste64/Rules.py @@ -77,7 +77,8 @@ def set_rules(world: Celeste64World): LocationName.strawberry_13: [[ItemName.breakables, ItemName.ground_dash], [ItemName.breakables, ItemName.air_dash]], LocationName.strawberry_14: [[ItemName.feather, ItemName.air_dash], - [ItemName.air_dash, ItemName.climb]], + [ItemName.air_dash, ItemName.climb], + [ItemName.double_dash_refills, ItemName.air_dash]], LocationName.strawberry_15: [[ItemName.feather], [ItemName.ground_dash, ItemName.air_dash]], LocationName.strawberry_17: [[ItemName.double_dash_refill, ItemName.traffic_block]], From b25509b311c65b6dc51c16a66c681c96437a8124 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Tue, 21 Jan 2025 20:30:55 -0500 Subject: [PATCH 14/22] Fix item name in rule --- worlds/celeste64/Rules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worlds/celeste64/Rules.py b/worlds/celeste64/Rules.py index bca213b7e297..57cf886e479b 100644 --- a/worlds/celeste64/Rules.py +++ b/worlds/celeste64/Rules.py @@ -78,7 +78,7 @@ def set_rules(world: Celeste64World): [ItemName.breakables, ItemName.air_dash]], LocationName.strawberry_14: [[ItemName.feather, ItemName.air_dash], [ItemName.air_dash, ItemName.climb], - [ItemName.double_dash_refills, ItemName.air_dash]], + [ItemName.double_dash_refill, ItemName.air_dash]], LocationName.strawberry_15: [[ItemName.feather], [ItemName.ground_dash, ItemName.air_dash]], LocationName.strawberry_17: [[ItemName.double_dash_refill, ItemName.traffic_block]], From 7bcb20efa7d71843e14ff406cceec8de89747d87 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Wed, 29 Jan 2025 23:16:52 -0500 Subject: [PATCH 15/22] Update Changelog --- worlds/celeste64/CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/worlds/celeste64/CHANGELOG.md b/worlds/celeste64/CHANGELOG.md index a2e8e5cbd866..3c37b4fcfe5c 100644 --- a/worlds/celeste64/CHANGELOG.md +++ b/worlds/celeste64/CHANGELOG.md @@ -10,7 +10,7 @@ - Hair Color - Allows for setting of Maddy's hair color in each of No Dash, One Dash, Two Dash, and Feather states - Other Player Ghosts - - A game config option allows you to see ghosts of other Celeste 64 players in the world + - A game config option allows you to see ghosts of other Celeste 64 players in the multiworld ### Quality of Life: @@ -18,6 +18,12 @@ - Received Checkpoint items allow for warping to their respective checkpoint - These items are on their respective checkpoint location if Checkpointsanity is disabled - Logic accounts for being able to warp to otherwise inaccessible areas + - Checkpoints are a possible option for a starting item on Standard Logic + Move Shuffle + Checkpointsanity +- New Options toggle to enable/disable background input + +### Bug Fixes: + +- Traffic Blocks now correctly appear disabled within Cassettes ## v1.2 From 59fab1b7c3deb2f867d361b003d43bfc8f4137f5 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Wed, 29 Jan 2025 23:17:13 -0500 Subject: [PATCH 16/22] Clarify Color option tooltip --- worlds/celeste64/Options.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/worlds/celeste64/Options.py b/worlds/celeste64/Options.py index 5044e6095a4f..2d991b99b803 100644 --- a/worlds/celeste64/Options.py +++ b/worlds/celeste64/Options.py @@ -90,7 +90,8 @@ class MadelineOneDashHairColor(TextChoice): The `any_color` option will choose a fully random color - A custom color entry must be a 6-character RGB hex color code + A custom color entry may be supplied as a 6-character RGB hex color code + e.g. F542C8 """ display_name = "Madeline One Dash Hair Color" option_strawberry = 0xDB2C00 @@ -128,7 +129,8 @@ class MadelineTwoDashHairColor(TextChoice): The `any_color` option will choose a fully random color - A custom color entry must be a 6-character RGB hex color code + A custom color entry may be supplied as a 6-character RGB hex color code + e.g. F542C8 """ display_name = "Madeline Two Dash Hair Color" option_strawberry = 0xDB2C00 @@ -166,7 +168,8 @@ class MadelineNoDashHairColor(TextChoice): The `any_color` option will choose a fully random color - A custom color entry must be a 6-character RGB hex color code + A custom color entry may be supplied as a 6-character RGB hex color code + e.g. F542C8 """ display_name = "Madeline No Dash Hair Color" option_strawberry = 0xDB2C00 @@ -204,7 +207,8 @@ class MadelineFeatherHairColor(TextChoice): The `any_color` option will choose a fully random color - A custom color entry must be a 6-character RGB hex color code + A custom color entry may be supplied as a 6-character RGB hex color code + e.g. F542C8 """ display_name = "Madeline Feather Hair Color" option_strawberry = 0xDB2C00 @@ -328,7 +332,7 @@ def resolve_options(world: World): # One Dash Hair if isinstance(world.options.madeline_one_dash_hair_color.value, str): try: - world.madeline_one_dash_hair_color = int(world.options.madeline_one_dash_hair_color.value[:6], 16) + world.madeline_one_dash_hair_color = int(world.options.madeline_one_dash_hair_color.value.strip("#")[:6], 16) except ValueError: raise OptionError(f"Invalid input for option `madeline_one_dash_hair_color`:" f"{world.options.madeline_one_dash_hair_color.value} for " @@ -341,7 +345,7 @@ def resolve_options(world: World): # Two Dash Hair if isinstance(world.options.madeline_two_dash_hair_color.value, str): try: - world.madeline_two_dash_hair_color = int(world.options.madeline_two_dash_hair_color.value[:6], 16) + world.madeline_two_dash_hair_color = int(world.options.madeline_two_dash_hair_color.value.strip("#")[:6], 16) except ValueError: raise OptionError(f"Invalid input for option `madeline_two_dash_hair_color`:" f"{world.options.madeline_two_dash_hair_color.value} for " @@ -354,7 +358,7 @@ def resolve_options(world: World): # No Dash Hair if isinstance(world.options.madeline_no_dash_hair_color.value, str): try: - world.madeline_no_dash_hair_color = int(world.options.madeline_no_dash_hair_color.value[:6], 16) + world.madeline_no_dash_hair_color = int(world.options.madeline_no_dash_hair_color.value.strip("#")[:6], 16) except ValueError: raise OptionError(f"Invalid input for option `madeline_no_dash_hair_color`:" f"{world.options.madeline_no_dash_hair_color.value} for " @@ -367,7 +371,7 @@ def resolve_options(world: World): # Feather Hair if isinstance(world.options.madeline_feather_hair_color.value, str): try: - world.madeline_feather_hair_color = int(world.options.madeline_feather_hair_color.value[:6], 16) + world.madeline_feather_hair_color = int(world.options.madeline_feather_hair_color.value.strip("#")[:6], 16) except ValueError: raise OptionError(f"Invalid input for option `madeline_feather_hair_color`:" f"{world.options.madeline_feather_hair_color.value} for " From f9a124e999765d518256cad6de0cef6a52dc0ce6 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Wed, 29 Jan 2025 23:17:30 -0500 Subject: [PATCH 17/22] Logic tweak --- worlds/celeste64/Rules.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/worlds/celeste64/Rules.py b/worlds/celeste64/Rules.py index 57cf886e479b..21cdb6538e47 100644 --- a/worlds/celeste64/Rules.py +++ b/worlds/celeste64/Rules.py @@ -25,8 +25,9 @@ def set_rules(world: Celeste64World): location_standard_moves_logic: Dict[str, List[List[str]]] = { LocationName.strawberry_1: [[ItemName.ground_dash], [ItemName.air_dash], - [ItemName.skid_jump], [ItemName.climb]], + LocationName.strawberry_2: [[ItemName.air_dash], + [ItemName.skid_jump]], LocationName.strawberry_3: [[ItemName.air_dash], [ItemName.skid_jump]], LocationName.strawberry_4: [[ItemName.traffic_block, ItemName.breakables, ItemName.air_dash]], From 448b1d1c7301692cfb3eb90eaced8dee1288acd0 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Wed, 29 Jan 2025 23:17:55 -0500 Subject: [PATCH 18/22] Use Checkpoints as possible starting items when relevant --- worlds/celeste64/__init__.py | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/worlds/celeste64/__init__.py b/worlds/celeste64/__init__.py index 853391f6575c..db473985dfe3 100644 --- a/worlds/celeste64/__init__.py +++ b/worlds/celeste64/__init__.py @@ -85,25 +85,32 @@ def create_items(self) -> None: for name in unlockable_item_data_table.keys() if name not in self.options.start_inventory] - if self.options.move_shuffle: - move_items_for_itempool: List[str] = deepcopy(list(move_item_data_table.keys())) + chosen_start_item: str = "" + if self.options.move_shuffle: if self.options.logic_difficulty == "standard": - # If the start_inventory already includes a move, don't worry about giving it one - if not [move for move in move_items_for_itempool if move in self.options.start_inventory]: - chosen_start_move = self.random.choice(move_items_for_itempool) - move_items_for_itempool.remove(chosen_start_move) + possible_unwalls: List[str] = [name for name in move_item_data_table.keys() + if name != ItemName.skid_jump] + + if self.options.checkpointsanity: + possible_unwalls.extend([name for name in checkpoint_item_data_table.keys() + if name != ItemName.checkpoint_1 and name != ItemName.checkpoint_10]) + + # If the start_inventory already includes a move or checkpoint, don't worry about giving it one + if not [item for item in possible_unwalls if item in self.multiworld.precollected_items[self.player]]: + chosen_start_item = self.random.choice(possible_unwalls) if self.options.carsanity: intro_car_loc: Location = self.multiworld.get_location(LocationName.car_1, self.player) - intro_car_loc.place_locked_item(self.create_item(chosen_start_move)) + intro_car_loc.place_locked_item(self.create_item(chosen_start_item)) location_count -= 1 else: - self.multiworld.push_precollected(self.create_item(chosen_start_move)) + self.multiworld.push_precollected(self.create_item(chosen_start_item)) item_pool += [self.create_item(name) - for name in move_items_for_itempool - if name not in self.options.start_inventory] + for name in move_item_data_table.keys() + if name not in self.multiworld.precollected_items[self.player] + and name != chosen_start_item] else: for start_move in move_item_data_table.keys(): self.multiworld.push_precollected(self.create_item(start_move)) @@ -114,7 +121,9 @@ def create_items(self) -> None: goal_checkpoint_loc.place_locked_item(self.create_item(ItemName.checkpoint_10)) item_pool += [self.create_item(name) for name in checkpoint_item_data_table.keys() - if name not in self.options.start_inventory and name != ItemName.checkpoint_10] + if name not in self.multiworld.precollected_items[self.player] + and name != ItemName.checkpoint_10 + and name != chosen_start_item] else: for item_name in checkpoint_item_data_table.keys(): checkpoint_loc: Location = self.multiworld.get_location(item_name, self.player) From 8917c0ec9e37588d0feb57892610f05c04fe823f Mon Sep 17 00:00:00 2001 From: PoryGone Date: Thu, 30 Jan 2025 02:16:55 -0500 Subject: [PATCH 19/22] Review comments --- worlds/celeste64/Options.py | 118 ++++++------------------------------ worlds/celeste64/Rules.py | 11 ++-- 2 files changed, 25 insertions(+), 104 deletions(-) diff --git a/worlds/celeste64/Options.py b/worlds/celeste64/Options.py index 2d991b99b803..d08789a85d26 100644 --- a/worlds/celeste64/Options.py +++ b/worlds/celeste64/Options.py @@ -84,16 +84,7 @@ class Checkpointsanity(Toggle): display_name = "Checkpointsanity" -class MadelineOneDashHairColor(TextChoice): - """ - What color Madeline's hair is when she has one dash - - The `any_color` option will choose a fully random color - - A custom color entry may be supplied as a 6-character RGB hex color code - e.g. F542C8 - """ - display_name = "Madeline One Dash Hair Color" +class ColorChoice(TextChoice): option_strawberry = 0xDB2C00 option_empty = 0x6EC0FF option_double = 0xFA91FF @@ -112,7 +103,6 @@ class MadelineOneDashHairColor(TextChoice): option_white = 0xFFFFFF option_grey = 0x808080 option_any_color = -1 - default = option_strawberry @classmethod def from_text(cls, text: str) -> Choice: @@ -123,7 +113,20 @@ def from_text(cls, text: str) -> Choice: return cls(random.choice(choice_list)) return super().from_text(text) -class MadelineTwoDashHairColor(TextChoice): + +class MadelineOneDashHairColor(ColorChoice): + """ + What color Madeline's hair is when she has one dash + + The `any_color` option will choose a fully random color + + A custom color entry may be supplied as a 6-character RGB hex color code + e.g. F542C8 + """ + display_name = "Madeline One Dash Hair Color" + default = ColorChoice.option_strawberry + +class MadelineTwoDashHairColor(ColorChoice): """ What color Madeline's hair is when she has two dashes @@ -133,36 +136,9 @@ class MadelineTwoDashHairColor(TextChoice): e.g. F542C8 """ display_name = "Madeline Two Dash Hair Color" - option_strawberry = 0xDB2C00 - option_empty = 0x6EC0FF - option_double = 0xFA91FF - option_golden = 0xF2D450 - option_baddy = 0x9B3FB5 - option_fire_red = 0xFF0000 - option_maroon = 0x800000 - option_salmon = 0xFF3A65 - option_orange = 0xD86E0A - option_lime_green = 0x8DF920 - option_bright_green = 0x0DAF05 - option_forest_green = 0x132818 - option_royal_blue = 0x0036BF - option_brown = 0xB78726 - option_black = 0x000000 - option_white = 0xFFFFFF - option_grey = 0x808080 - option_any_color = -1 - default = option_double + default = ColorChoice.option_double - @classmethod - def from_text(cls, text: str) -> Choice: - text = text.lower() - if text == "random": - choice_list = list(cls.name_lookup) - choice_list.remove(-1) - return cls(random.choice(choice_list)) - return super().from_text(text) - -class MadelineNoDashHairColor(TextChoice): +class MadelineNoDashHairColor(ColorChoice): """ What color Madeline's hair is when she has no dashes @@ -172,36 +148,9 @@ class MadelineNoDashHairColor(TextChoice): e.g. F542C8 """ display_name = "Madeline No Dash Hair Color" - option_strawberry = 0xDB2C00 - option_empty = 0x6EC0FF - option_double = 0xFA91FF - option_golden = 0xF2D450 - option_baddy = 0x9B3FB5 - option_fire_red = 0xFF0000 - option_maroon = 0x800000 - option_salmon = 0xFF3A65 - option_orange = 0xD86E0A - option_lime_green = 0x8DF920 - option_bright_green = 0x0DAF05 - option_forest_green = 0x132818 - option_royal_blue = 0x0036BF - option_brown = 0xB78726 - option_black = 0x000000 - option_white = 0xFFFFFF - option_grey = 0x808080 - option_any_color = -1 - default = option_empty - - @classmethod - def from_text(cls, text: str) -> Choice: - text = text.lower() - if text == "random": - choice_list = list(cls.name_lookup) - choice_list.remove(-1) - return cls(random.choice(choice_list)) - return super().from_text(text) + default = ColorChoice.option_empty -class MadelineFeatherHairColor(TextChoice): +class MadelineFeatherHairColor(ColorChoice): """ What color Madeline's hair is when she has a feather @@ -211,34 +160,7 @@ class MadelineFeatherHairColor(TextChoice): e.g. F542C8 """ display_name = "Madeline Feather Hair Color" - option_strawberry = 0xDB2C00 - option_empty = 0x6EC0FF - option_double = 0xFA91FF - option_golden = 0xF2D450 - option_baddy = 0x9B3FB5 - option_fire_red = 0xFF0000 - option_maroon = 0x800000 - option_salmon = 0xFF3A65 - option_orange = 0xD86E0A - option_lime_green = 0x8DF920 - option_bright_green = 0x0DAF05 - option_forest_green = 0x132818 - option_royal_blue = 0x0036BF - option_brown = 0xB78726 - option_black = 0x000000 - option_white = 0xFFFFFF - option_grey = 0x808080 - option_any_color = -1 - default = option_golden - - @classmethod - def from_text(cls, text: str) -> Choice: - text = text.lower() - if text == "random": - choice_list = list(cls.name_lookup) - choice_list.remove(-1) - return cls(random.choice(choice_list)) - return super().from_text(text) + default = ColorChoice.option_golden class BadelineChaserSource(Choice): diff --git a/worlds/celeste64/Rules.py b/worlds/celeste64/Rules.py index 21cdb6538e47..3365a7cf9551 100644 --- a/worlds/celeste64/Rules.py +++ b/worlds/celeste64/Rules.py @@ -204,13 +204,11 @@ def location_rule(state: CollectionState, world: Celeste64World, loc: str) -> bo return False -def region_connection_rule(state: CollectionState, world: Celeste64World, source_reg: str, dest_reg: str) -> bool: - connection: Tuple[str] = (source_reg, dest_reg) - - if connection not in world.active_region_logic_mapping: +def region_connection_rule(state: CollectionState, world: Celeste64World, region_connection: Tuple[str]) -> bool: + if region_connection not in world.active_region_logic_mapping: return True - for possible_access in world.active_region_logic_mapping[connection]: + for possible_access in world.active_region_logic_mapping[region_connection]: if state.has_all(possible_access, world.player): return True @@ -227,6 +225,7 @@ def connect_region(world: Celeste64World, region: Region, dest_regions: List[str rules: Dict[str, Callable[[CollectionState], bool]] = {} for dest_region in dest_regions: - rules[dest_region] = lambda state, dest_region=dest_region: region_connection_rule(state, world, region.name, dest_region) + region_connection: Tuple[str] = (region.name, dest_region) + rules[dest_region] = lambda state, region_connection=region_connection: region_connection_rule(state, world, region_connection) region.add_exits(dest_regions, rules) From 1404a758d13f1f78d692b2518ee1bd06879943b8 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Thu, 30 Jan 2025 18:42:24 -0500 Subject: [PATCH 20/22] Use Property --- worlds/celeste64/Options.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/worlds/celeste64/Options.py b/worlds/celeste64/Options.py index d08789a85d26..bb9932d47f0d 100644 --- a/worlds/celeste64/Options.py +++ b/worlds/celeste64/Options.py @@ -258,7 +258,7 @@ def resolve_options(world: World): except ValueError: raise OptionError(f"Invalid input for option `madeline_one_dash_hair_color`:" f"{world.options.madeline_one_dash_hair_color.value} for " - f"{world.multiworld.get_player_name(world.player)}") + f"{world.player_name}") elif world.options.madeline_one_dash_hair_color.value == -1: world.madeline_one_dash_hair_color = world.random.randint(0, 0xFFFFFF) else: @@ -271,7 +271,7 @@ def resolve_options(world: World): except ValueError: raise OptionError(f"Invalid input for option `madeline_two_dash_hair_color`:" f"{world.options.madeline_two_dash_hair_color.value} for " - f"{world.multiworld.get_player_name(world.player)}") + f"{world.player_name}") elif world.options.madeline_two_dash_hair_color.value == -1: world.madeline_two_dash_hair_color = world.random.randint(0, 0xFFFFFF) else: @@ -284,7 +284,7 @@ def resolve_options(world: World): except ValueError: raise OptionError(f"Invalid input for option `madeline_no_dash_hair_color`:" f"{world.options.madeline_no_dash_hair_color.value} for " - f"{world.multiworld.get_player_name(world.player)}") + f"{world.player_name}") elif world.options.madeline_no_dash_hair_color.value == -1: world.madeline_no_dash_hair_color = world.random.randint(0, 0xFFFFFF) else: @@ -297,7 +297,7 @@ def resolve_options(world: World): except ValueError: raise OptionError(f"Invalid input for option `madeline_feather_hair_color`:" f"{world.options.madeline_feather_hair_color.value} for " - f"{world.multiworld.get_player_name(world.player)}") + f"{world.player_name}") elif world.options.madeline_feather_hair_color.value == -1: world.madeline_feather_hair_color = world.random.randint(0, 0xFFFFFF) else: From 3fbec9189e903a40c465d1997366c1209fcd3221 Mon Sep 17 00:00:00 2001 From: PoryGone Date: Wed, 5 Feb 2025 00:33:29 -0500 Subject: [PATCH 21/22] Comply with other games' bad behavior --- worlds/celeste64/__init__.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/worlds/celeste64/__init__.py b/worlds/celeste64/__init__.py index db473985dfe3..04eae0c444a9 100644 --- a/worlds/celeste64/__init__.py +++ b/worlds/celeste64/__init__.py @@ -181,16 +181,15 @@ def create_regions(self) -> None: from .Rules import connect_region connect_region(self, region, region_data_table[region_name].connecting_regions) + # Have to do this here because of other games using State in a way that's bad + from .Rules import set_rules + set_rules(self) + def get_filler_item_name(self) -> str: return ItemName.raspberry - def set_rules(self) -> None: - from .Rules import set_rules - set_rules(self) - - def fill_slot_data(self): return { "death_link": self.options.death_link.value, From 7419d04f7b9269edf8a48a4e010142c45faf6b2e Mon Sep 17 00:00:00 2001 From: PoryGone <98504756+PoryGone@users.noreply.github.com> Date: Wed, 12 Feb 2025 02:42:44 -0500 Subject: [PATCH 22/22] Apply suggestions from code review Co-authored-by: Silvris <58583688+Silvris@users.noreply.github.com> --- worlds/celeste64/Options.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/worlds/celeste64/Options.py b/worlds/celeste64/Options.py index bb9932d47f0d..71e0cfa763c8 100644 --- a/worlds/celeste64/Options.py +++ b/worlds/celeste64/Options.py @@ -109,7 +109,7 @@ def from_text(cls, text: str) -> Choice: text = text.lower() if text == "random": choice_list = list(cls.name_lookup) - choice_list.remove(-1) + choice_list.remove(cls.option_any_color) return cls(random.choice(choice_list)) return super().from_text(text) @@ -259,7 +259,7 @@ def resolve_options(world: World): raise OptionError(f"Invalid input for option `madeline_one_dash_hair_color`:" f"{world.options.madeline_one_dash_hair_color.value} for " f"{world.player_name}") - elif world.options.madeline_one_dash_hair_color.value == -1: + elif world.options.madeline_one_dash_hair_color.value == ColorChoice.option_any_color: world.madeline_one_dash_hair_color = world.random.randint(0, 0xFFFFFF) else: world.madeline_one_dash_hair_color = world.options.madeline_one_dash_hair_color.value @@ -272,7 +272,7 @@ def resolve_options(world: World): raise OptionError(f"Invalid input for option `madeline_two_dash_hair_color`:" f"{world.options.madeline_two_dash_hair_color.value} for " f"{world.player_name}") - elif world.options.madeline_two_dash_hair_color.value == -1: + elif world.options.madeline_two_dash_hair_color.value == ColorChoice.option_any_color: world.madeline_two_dash_hair_color = world.random.randint(0, 0xFFFFFF) else: world.madeline_two_dash_hair_color = world.options.madeline_two_dash_hair_color.value @@ -285,7 +285,7 @@ def resolve_options(world: World): raise OptionError(f"Invalid input for option `madeline_no_dash_hair_color`:" f"{world.options.madeline_no_dash_hair_color.value} for " f"{world.player_name}") - elif world.options.madeline_no_dash_hair_color.value == -1: + elif world.options.madeline_no_dash_hair_color.value == ColorChoice.option_any_color: world.madeline_no_dash_hair_color = world.random.randint(0, 0xFFFFFF) else: world.madeline_no_dash_hair_color = world.options.madeline_no_dash_hair_color.value @@ -298,7 +298,7 @@ def resolve_options(world: World): raise OptionError(f"Invalid input for option `madeline_feather_hair_color`:" f"{world.options.madeline_feather_hair_color.value} for " f"{world.player_name}") - elif world.options.madeline_feather_hair_color.value == -1: + elif world.options.madeline_feather_hair_color.value == ColorChoice.option_any_color: world.madeline_feather_hair_color = world.random.randint(0, 0xFFFFFF) else: world.madeline_feather_hair_color = world.options.madeline_feather_hair_color.value