Files
dockipelago/worlds/aquaria/Regions.py
Louis M 13b6a5f4b2 Aquaria: Adding a lots of options and one check (#4414)
First, there is one check that has been added. The location is "Sitting on the throne before the cathedral with the crest on it" and the item is the "Opening of the Cathedral door". In Vanilla, sitting on the crested throne open the door to the cathedral.

Now for the options added:
- infinite_hot_soup: Make the game impossible to run out of hot soup once you got it as an item.
- open_body_tongue: The body level (the ending level) is blocked by a big tongue. This option remove the tongue without having to go to the Sunken City (where it is normally removed)
- maximum_ingredient_amount: In the Vanilla game, the ingredients and dishes count is limited to 8. This option make this count configurable.
- skip_final_boss_3rd_form: The final boss has 5 forms. The 3rd one is long and not really challenging. So, this option is used to skip this form.
- save_healing: Normally, the save points heal the player. There is also beds in the game that can heal the player. This option removed the healing from the save point and forced the player to heal using beds (or healing monsters or healing items)
- no_progression_(whatever): Make this "whatever" (generally regions) exempt of progression items. Note that this is not using the exclusion-feature of AP, as these locations may still contain 'Useful' items. It is only guaranteed that no 'Progression' and 'Progression_Skip_Balancing'-items will appear in these regions. This option does not remove locations. I did not exclude or completely remove the regions because I don't have enough location to put every useful item in the game.

There is also 2 new goals:
- Four gods: The goal is obtained when the player beat the four gods (this is something like half the game). Useful to have quicker runs
- Gods and Creator: Like the Four Gods run, but when the four gods are obtained, that open a transportation turtle to the final boss (the Creator) and the player have to beat the final boss to obtain the goal.

Note that for the 2 new goals, all locations from the last 4 areas (Abyss, Frozen Veil, Sunken City and The Body) are completely removed (not just excluded).
2026-02-15 19:20:45 +01:00

1542 lines
92 KiB
Python
Executable File

"""
Author: Louis M
Date: Fri, 15 Mar 2024 18:41:40 +0000
Description: Used to manage Regions in the Aquaria game multiworld randomizer
"""
from typing import Dict, Optional, Iterable
from BaseClasses import MultiWorld, Region, Entrance, Item, ItemClassification, CollectionState
from .Items import AquariaItem, ItemNames
from .Locations import AquariaLocations, AquariaLocation, AquariaLocationNames
from .Options import AquariaOptions, UnconfineHomeWater, LightNeededToGetToDarkPlaces, Objective
from worlds.generic.Rules import add_rule, set_rule
# Every condition to connect regions
def _has_hot_soup(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the hotsoup item"""
return state.has_any({ItemNames.HOT_SOUP, ItemNames.HOT_SOUP_X_2}, player)
def _has_tongue_cleared(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the Body tongue cleared item"""
return state.has(ItemNames.BODY_TONGUE_CLEARED, player)
def _has_sun_crystal(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the Sun crystal item"""
return state.has(ItemNames.HAS_SUN_CRYSTAL, player) and _has_bind_song(state, player)
def _has_li(state: CollectionState, player: int) -> bool:
"""`player` in `state` has Li in its team"""
return state.has(ItemNames.LI_AND_LI_SONG, player)
DAMAGING_ITEMS:Iterable[str] = [
ItemNames.ENERGY_FORM, ItemNames.NATURE_FORM, ItemNames.BEAST_FORM,
ItemNames.LI_AND_LI_SONG, ItemNames.BABY_NAUTILUS, ItemNames.BABY_PIRANHA,
ItemNames.BABY_BLASTER
]
def _has_damaging_item(state: CollectionState, player: int, damaging_items:Iterable[str] = DAMAGING_ITEMS) -> bool:
"""`player` in `state` has the an item that do damage other than the ones in `to_remove`"""
return state.has_any(damaging_items, player)
def _has_energy_attack_item(state: CollectionState, player: int) -> bool:
"""`player` in `state` has items that can do a lot of damage (enough to beat bosses)"""
return _has_energy_form(state, player) or _has_dual_form(state, player)
def _has_shield_song(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the shield song item"""
return state.has(ItemNames.SHIELD_SONG, player)
def _has_bind_song(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the bind song item"""
return state.has(ItemNames.BIND_SONG, player)
def _has_energy_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the energy form item"""
return state.has(ItemNames.ENERGY_FORM, player)
def _has_beast_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the beast form item"""
return state.has(ItemNames.BEAST_FORM, player)
def _has_beast_and_soup_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the beast form item"""
return _has_beast_form(state, player) and _has_hot_soup(state, player)
def _has_beast_form_or_arnassi_armor(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the beast form item"""
return _has_beast_form(state, player) or state.has(ItemNames.ARNASSI_ARMOR, player)
def _has_nature_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the nature form item"""
return state.has(ItemNames.NATURE_FORM, player)
def _has_sun_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the sun form item"""
return state.has(ItemNames.SUN_FORM, player)
def _has_light(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the light item"""
return state.has(ItemNames.BABY_DUMBO, player) or _has_sun_form(state, player)
def _has_dual_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the dual form item"""
return _has_li(state, player) and state.has(ItemNames.DUAL_FORM, player)
def _has_fish_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the fish form item"""
return state.has(ItemNames.FISH_FORM, player)
def _has_spirit_form(state: CollectionState, player: int) -> bool:
"""`player` in `state` has the spirit form item"""
return state.has(ItemNames.SPIRIT_FORM, player)
def _has_big_bosses(state: CollectionState, player: int) -> bool:
"""`player` in `state` has beated every big bosses"""
return state.has_all({ItemNames.FALLEN_GOD_BEATED, ItemNames.MITHALAN_GOD_BEATED, ItemNames.DRUNIAN_GOD_BEATED,
ItemNames.LUMEREAN_GOD_BEATED, ItemNames.THE_GOLEM_BEATED}, player)
def _has_four_gods_beated(state: CollectionState, player: int) -> bool:
"""`player` in `state` has beated every big bosses"""
return state.has_all({ItemNames.FALLEN_GOD_BEATED, ItemNames.MITHALAN_GOD_BEATED, ItemNames.DRUNIAN_GOD_BEATED,
ItemNames.LUMEREAN_GOD_BEATED}, player)
def _has_mini_bosses(state: CollectionState, player: int) -> bool:
"""`player` in `state` has beated every mini bosses"""
return state.has_all({ItemNames.NAUTILUS_PRIME_BEATED, ItemNames.BLASTER_PEG_PRIME_BEATED, ItemNames.MERGOG_BEATED,
ItemNames.MITHALAN_PRIESTS_BEATED, ItemNames.OCTOPUS_PRIME_BEATED,
ItemNames.CRABBIUS_MAXIMUS_BEATED, ItemNames.MANTIS_SHRIMP_PRIME_BEATED,
ItemNames.KING_JELLYFISH_GOD_PRIME_BEATED}, player)
def _has_mini_bosses_four_gods(state: CollectionState, player: int) -> bool:
"""`player` in `state` has beated every mini bosses other than the ones in the abyss and in the bubble cave"""
return state.has_all({ItemNames.NAUTILUS_PRIME_BEATED, ItemNames.BLASTER_PEG_PRIME_BEATED, ItemNames.MERGOG_BEATED,
ItemNames.MITHALAN_PRIESTS_BEATED, ItemNames.OCTOPUS_PRIME_BEATED,
ItemNames.CRABBIUS_MAXIMUS_BEATED}, player)
def _has_secrets(state: CollectionState, player: int) -> bool:
"""The secrets have been acquired in the `state` of the `player`"""
return state.has_all({ItemNames.FIRST_SECRET_OBTAINED, ItemNames.SECOND_SECRET_OBTAINED,
ItemNames.THIRD_SECRET_OBTAINED}, player)
def _item_not_advancement(item: Item):
"""The `item` is not an advancement item"""
return not item.advancement
def _is_cathedral_door_opened(state: CollectionState, player: int) -> bool:
"""The door to Mithalas Cathedral has been opened in the `state` of the `player`"""
return state.has(ItemNames.DOOR_TO_CATHEDRAL, player)
class AquariaRegions:
"""
Class used to create regions of the Aquaria game
"""
menu: Region
verse_cave_r: Region
verse_cave_l: Region
home_water: Region
home_water_behind_rocks: Region
home_water_nautilus: Region
home_water_transturtle: Region
naija_home: Region
song_cave: Region
energy_temple_1: Region
energy_temple_2: Region
energy_temple_3: Region
energy_temple_boss: Region
energy_temple_4: Region
energy_temple_idol: Region
energy_temple_blaster_room: Region
energy_temple_altar: Region
openwater_tl: Region
openwater_tr: Region
openwater_tr_turtle: Region
openwater_tr_urns: Region
openwater_bl: Region
openwater_br: Region
skeleton_path: Region
skeleton_path_sc: Region
arnassi: Region
arnassi_cave_transturtle: Region
arnassi_cave: Region
arnassi_crab_boss: Region
simon: Region
mithalas_city: Region
mithalas_city_urns: Region
mithalas_city_top_path: Region
mithalas_city_fishpass: Region
mithalas_castle: Region
mithalas_castle_urns: Region
mithalas_castle_tube: Region
mithalas_castle_sc: Region
cathedral_top: Region
cathedral_top_start: Region
cathedral_top_start_urns: Region
cathedral_top_end: Region
cathedral_underground: Region
cathedral_boss_l: Region
cathedral_boss_r: Region
forest_tl: Region
forest_tl_verse_egg_room: Region
forest_tr: Region
forest_tr_fp: Region
forest_bl: Region
forest_bl_sc: Region
forest_br: Region
forest_boss: Region
forest_boss_entrance: Region
sprite_cave: Region
sprite_cave_tube: Region
mermog_cave: Region
mermog_boss: Region
forest_fish_cave: Region
veil_tl: Region
veil_tl_fp: Region
veil_tr_l: Region
veil_tr_l_fp: Region
veil_tr_r: Region
veil_b: Region
veil_b_sc: Region
veil_b_fp: Region
veil_br: Region
octo_cave_t: Region
octo_cave_b: Region
turtle_cave: Region
turtle_cave_bubble: Region
sun_temple_l: Region
sun_temple_l_entrance: Region
sun_temple_r: Region
sun_temple_boss_path: Region
sun_temple_boss: Region
abyss_l: Region
abyss_lb: Region
abyss_r: Region
abyss_r_transturtle: Region
ice_cave: Region
frozen_feil: Region
bubble_cave: Region
bubble_cave_boss: Region
king_jellyfish_cave: Region
abyss_r_whale: Region
whale: Region
first_secret: Region
sunken_city_l: Region
sunken_city_l_crates: Region
sunken_city_r_crates: Region
sunken_city_boss: Region
sunken_city_l_bedroom: Region
body_c: Region
body_l: Region
body_rt: Region
body_rb: Region
body_b: Region
final_boss_lobby: Region
final_boss_tube: Region
final_boss: Region
final_boss_end: Region
four_gods_end: Region
"""
Every Region of the game
"""
multiworld: MultiWorld
"""
The Current Multiworld game.
"""
player: int
"""
The ID of the player
"""
is_four_gods: bool
"""
True if the player has an objective that implies killing the four gods
"""
def __add_region(self, hint: str,
locations: Optional[Dict[str, int]]) -> Region:
"""
Create a new Region, add it to the `world` regions and return it.
Be aware that this function have a side effect on ``world`.`regions`
"""
region: Region = Region(hint, self.player, self.multiworld, hint)
if locations is not None:
region.add_locations(locations, AquariaLocation)
return region
def __create_home_water_area(self) -> None:
"""
Create the `verse_cave`, `home_water` and `song_cave*` regions
"""
self.menu = self.__add_region("Menu", None)
self.verse_cave_r = self.__add_region("Verse Cave right area",
AquariaLocations.locations_verse_cave_r)
self.verse_cave_l = self.__add_region("Verse Cave left area",
AquariaLocations.locations_verse_cave_l)
self.home_water = self.__add_region("Home Waters", AquariaLocations.locations_home_water)
self.home_water_nautilus = self.__add_region("Home Waters, Nautilus nest",
AquariaLocations.locations_home_water_nautilus)
self.home_water_transturtle = self.__add_region("Home Waters, turtle room",
AquariaLocations.locations_home_water_transturtle)
self.home_water_behind_rocks = self.__add_region("Home Waters, behind rock",
AquariaLocations.locations_home_water_behind_rocks)
self.naija_home = self.__add_region("Naija's Home", AquariaLocations.locations_naija_home)
self.song_cave = self.__add_region("Song Cave", AquariaLocations.locations_song_cave)
def __create_energy_temple(self) -> None:
"""
Create the `energy_temple_*` regions
"""
self.energy_temple_1 = self.__add_region("Energy Temple first area",
AquariaLocations.locations_energy_temple_1)
self.energy_temple_2 = self.__add_region("Energy Temple second area",
AquariaLocations.locations_energy_temple_2)
self.energy_temple_3 = self.__add_region("Energy Temple third area",
AquariaLocations.locations_energy_temple_3)
self.energy_temple_altar = self.__add_region("Energy Temple bottom entrance",
AquariaLocations.locations_energy_temple_altar)
self.energy_temple_boss = self.__add_region("Energy Temple fallen God room",
AquariaLocations.locations_energy_temple_boss)
self.energy_temple_idol = self.__add_region("Energy Temple Idol room",
AquariaLocations.locations_energy_temple_idol)
self.energy_temple_blaster_room = self.__add_region("Energy Temple blaster room",
AquariaLocations.locations_energy_temple_blaster_room)
self.energy_temple_4 = self.__add_region("Energy Temple after boss path", None)
def __create_openwater(self) -> None:
"""
Create the `openwater_*`, `skeleton_path`, `arnassi*` and `simon`
regions
"""
self.openwater_tl = self.__add_region("Open Waters top left area",
AquariaLocations.locations_openwater_tl)
self.openwater_tr = self.__add_region("Open Waters top right area",
AquariaLocations.locations_openwater_tr)
self.openwater_tr_turtle = self.__add_region("Open Waters top right area, turtle room",
AquariaLocations.locations_openwater_tr_turtle)
self.openwater_tr_urns = self.__add_region("Open Waters top right area, Mithalas entrance",
AquariaLocations.locations_openwater_tr_urns)
self.openwater_bl = self.__add_region("Open Waters bottom left area",
AquariaLocations.locations_openwater_bl)
self.openwater_br = self.__add_region("Open Waters bottom right area", None)
self.skeleton_path = self.__add_region("Open Waters skeleton path",
AquariaLocations.locations_skeleton_path)
self.skeleton_path_sc = self.__add_region("Open Waters skeleton path spirit crystal",
AquariaLocations.locations_skeleton_path_sc)
self.arnassi = self.__add_region("Arnassi Ruins", AquariaLocations.locations_arnassi)
self.arnassi_cave = self.__add_region("Arnassi Ruins cave",
AquariaLocations.locations_arnassi_cave)
self.arnassi_cave_transturtle = self.__add_region("Arnassi Ruins cave, transturtle area",
AquariaLocations.locations_arnassi_cave_transturtle)
self.arnassi_crab_boss = self.__add_region("Arnassi Ruins, Crabbius Maximus lair",
AquariaLocations.locations_arnassi_crab_boss)
def __create_mithalas(self) -> None:
"""
Create the `mithalas_city*` and `cathedral_*` regions
"""
self.mithalas_city = self.__add_region("Mithalas City",
AquariaLocations.locations_mithalas_city)
self.mithalas_city_urns = self.__add_region("Mithalas City urns", AquariaLocations.locations_mithalas_city_urns)
self.mithalas_city_fishpass = self.__add_region("Mithalas City fish pass",
AquariaLocations.locations_mithalas_city_fishpass)
self.mithalas_city_top_path = self.__add_region("Mithalas City top path",
AquariaLocations.locations_mithalas_city_top_path)
self.mithalas_castle = self.__add_region("Mithalas castle", AquariaLocations.locations_mithalas_castle)
self.mithalas_castle_urns = self.__add_region("Mithalas castle urns",
AquariaLocations.locations_mithalas_castle_urns)
self.mithalas_castle_tube = self.__add_region("Mithalas castle, plant tube entrance",
AquariaLocations.locations_mithalas_castle_tube)
self.mithalas_castle_sc = self.__add_region("Mithalas castle spirit crystal",
AquariaLocations.locations_mithalas_castle_sc)
self.cathedral_top_start = self.__add_region("Mithalas Cathedral start",
AquariaLocations.locations_cathedral_top_start)
self.cathedral_top_start_urns = self.__add_region("Mithalas Cathedral start urns",
AquariaLocations.locations_cathedral_top_start_urns)
self.cathedral_top_end = self.__add_region("Mithalas Cathedral end",
AquariaLocations.locations_cathedral_top_end)
self.cathedral_underground = self.__add_region("Mithalas Cathedral underground",
AquariaLocations.locations_cathedral_underground)
self.cathedral_boss_l = self.__add_region("Mithalas Cathedral, after Mithalan God",
AquariaLocations.locations_cathedral_boss)
self.cathedral_boss_r = self.__add_region("Mithalas Cathedral, before Mithalan God", None)
def __create_forest(self) -> None:
"""
Create the `forest_*` dans `mermog_cave` regions
"""
self.forest_tl = self.__add_region("Kelp Forest top left area",
AquariaLocations.locations_forest_tl)
self.forest_tl_verse_egg_room = self.__add_region("Kelp Forest top left area fish pass",
AquariaLocations.locations_forest_tl_verse_egg_room)
self.forest_tr = self.__add_region("Kelp Forest top right area",
AquariaLocations.locations_forest_tr)
self.forest_tr_fp = self.__add_region("Kelp Forest top right area fish pass",
AquariaLocations.locations_forest_tr_fp)
self.forest_bl = self.__add_region("Kelp Forest bottom left area",
AquariaLocations.locations_forest_bl)
self.forest_bl_sc = self.__add_region("Kelp Forest bottom left area, spirit crystals",
AquariaLocations.locations_forest_bl_sc)
self.forest_br = self.__add_region("Kelp Forest bottom right area",
AquariaLocations.locations_forest_br)
self.sprite_cave = self.__add_region("Sprite cave",
AquariaLocations.locations_sprite_cave)
self.sprite_cave_tube = self.__add_region("Sprite cave after the plant tube",
AquariaLocations.locations_sprite_cave_tube)
self.forest_boss = self.__add_region("Kelp Forest Drunian God room",
AquariaLocations.locations_forest_boss)
self.forest_boss_entrance = self.__add_region("Kelp Forest Drunian God room entrance",
AquariaLocations.locations_forest_boss_entrance)
self.mermog_cave = self.__add_region("Mermog cave",
AquariaLocations.locations_mermog_cave)
self.mermog_boss = self.__add_region("Mermog cave boss",
AquariaLocations.locations_mermog_boss)
self.forest_fish_cave = self.__add_region("Kelp Forest fish cave",
AquariaLocations.locations_forest_fish_cave)
self.simon = self.__add_region("Simon Says area", AquariaLocations.locations_simon)
def __create_veil(self) -> None:
"""
Create the `veil_*`, `octo_cave` and `turtle_cave` regions
"""
self.veil_tl = self.__add_region("The Veil top left area", AquariaLocations.locations_veil_tl)
self.veil_tl_fp = self.__add_region("The Veil top left area fish pass",
AquariaLocations.locations_veil_tl_fp)
self.turtle_cave = self.__add_region("The Veil top left area, turtle cave",
AquariaLocations.locations_turtle_cave)
self.turtle_cave_bubble = self.__add_region("The Veil top left area, turtle cave Bubble Cliff",
AquariaLocations.locations_turtle_cave_bubble)
self.veil_tr_l = self.__add_region("The Veil top right area, left of temple",
AquariaLocations.locations_veil_tr_l)
self.veil_tr_l_fp = self.__add_region("The Veil top right area, fish pass left of temple", None)
self.veil_tr_r = self.__add_region("The Veil top right area, right of temple",
AquariaLocations.locations_veil_tr_r)
self.octo_cave_t = self.__add_region("Octopus Cave top entrance",
AquariaLocations.locations_octo_cave_t)
self.octo_cave_b = self.__add_region("Octopus Cave bottom entrance",
AquariaLocations.locations_octo_cave_b)
self.veil_b = self.__add_region("The Veil bottom left area",
AquariaLocations.locations_veil_b)
self.veil_b_sc = self.__add_region("The Veil bottom spirit crystal area",
AquariaLocations.locations_veil_b_sc)
self.veil_b_fp = self.__add_region("The Veil bottom left area, in the sunken ship",
AquariaLocations.locations_veil_b_fp)
self.veil_br = self.__add_region("The Veil bottom right area",
AquariaLocations.locations_veil_br)
def __create_sun_temple(self) -> None:
"""
Create the `sun_temple*` regions
"""
self.sun_temple_l = self.__add_region("Sun Temple left area",
AquariaLocations.locations_sun_temple_l)
self.sun_temple_l_entrance = self.__add_region("Sun Temple left area entrance", None)
self.sun_temple_r = self.__add_region("Sun Temple right area",
AquariaLocations.locations_sun_temple_r)
self.sun_temple_boss_path = self.__add_region("Sun Temple before boss area",
AquariaLocations.locations_sun_temple_boss_path)
self.sun_temple_boss = self.__add_region("Sun Temple boss area",
AquariaLocations.locations_sun_temple_boss)
def __create_abyss(self, add_locations: bool) -> None:
"""
Create the `abyss_*`, `ice_cave`, `king_jellyfish_cave` and `whale`
regions
"""
self.abyss_l = self.__add_region("Abyss left area",
AquariaLocations.locations_abyss_l if add_locations else None)
self.abyss_lb = self.__add_region("Abyss left bottom area",
AquariaLocations.locations_abyss_lb if add_locations else None)
self.abyss_r = self.__add_region("Abyss right area",
AquariaLocations.locations_abyss_r if add_locations else None)
self.abyss_r_transturtle = self.__add_region("Abyss right area, transturtle",
AquariaLocations.locations_abyss_r_transturtle)
self.abyss_r_whale = self.__add_region("Abyss right area, outside the whale",
AquariaLocations.locations_abyss_r_whale if add_locations else None)
self.ice_cave = self.__add_region("Ice Cavern",
AquariaLocations.locations_ice_cave if add_locations else None)
self.frozen_feil = self.__add_region("Frozen Veil", None)
self.bubble_cave = self.__add_region("Bubble Cave",
AquariaLocations.locations_bubble_cave if add_locations else None)
self.bubble_cave_boss = self.__add_region("Bubble Cave boss area",
AquariaLocations.locations_bubble_cave_boss
if add_locations else None)
self.king_jellyfish_cave = self.__add_region("Abyss left area, King jellyfish cave",
AquariaLocations.locations_king_jellyfish_cave
if add_locations else None)
self.whale = self.__add_region("Inside the whale",
AquariaLocations.locations_whale if add_locations else None)
self.first_secret = self.__add_region("First Secret area", None)
def __create_sunken_city(self, add_locations: bool) -> None:
"""
Create the `sunken_city_*` regions
"""
self.sunken_city_l = self.__add_region("Sunken City left area", None)
self.sunken_city_l_crates = self.__add_region("Sunken City left area",
AquariaLocations.locations_sunken_city_l
if add_locations else None)
self.sunken_city_l_bedroom = self.__add_region("Sunken City left area, bedroom",
AquariaLocations.locations_sunken_city_l_bedroom
if add_locations else None)
self.sunken_city_r = self.__add_region("Sunken City right area", None)
self.sunken_city_r_crates = self.__add_region("Sunken City right area crates",
AquariaLocations.locations_sunken_city_r
if add_locations else None)
self.sunken_city_boss = self.__add_region("Sunken City boss area",
AquariaLocations.locations_sunken_city_boss
if add_locations else None)
def __create_body(self, add_locations: bool) -> None:
"""
Create the `body_*` and `final_boss* regions
"""
self.body_c = self.__add_region("The Body center area",
AquariaLocations.locations_body_c if add_locations else None)
self.body_l = self.__add_region("The Body left area",
AquariaLocations.locations_body_l if add_locations else None)
self.body_rt = self.__add_region("The Body right area, top path",
AquariaLocations.locations_body_rt if add_locations else None)
self.body_rb = self.__add_region("The Body right area, bottom path",
AquariaLocations.locations_body_rb if add_locations else None)
self.body_b = self.__add_region("The Body bottom area",
AquariaLocations.locations_body_b if add_locations else None)
self.final_boss_lobby = self.__add_region("The Body, before final boss", None)
self.final_boss_tube = self.__add_region("The Body, final boss area turtle room",
AquariaLocations.locations_final_boss_tube
if add_locations else
AquariaLocations.locations_final_boss_tube_transturtle_only)
self.final_boss = self.__add_region("The Body, final boss",
AquariaLocations.locations_final_boss if add_locations else None)
self.final_boss_end = self.__add_region("The Body, final boss area", None)
@staticmethod
def get_entrance_name(from_region: Region, to_region: Region):
"""
Return the name of an entrance between `from_region` and `to_region`
"""
return from_region.name + " to " + to_region.name
def __connect_one_way_regions(self, source_region: Region, destination_region: Region, rule=None) -> None:
"""
Connect from the `source_region` to the `destination_region`
"""
entrance = Entrance(self.player, self.get_entrance_name(source_region, destination_region), source_region)
source_region.exits.append(entrance)
entrance.connect(destination_region)
if rule is not None:
set_rule(entrance, rule)
def __connect_regions(self, source_region: Region,
destination_region: Region, rule=None) -> None:
"""
Connect the `source_region` and the `destination_region` (two-way)
"""
self.__connect_one_way_regions(source_region, destination_region, rule)
self.__connect_one_way_regions(destination_region, source_region, rule)
def __connect_home_water_regions(self) -> None:
"""
Connect entrances of the different regions around `home_water`
"""
self.__connect_one_way_regions(self.menu, self.verse_cave_r)
self.__connect_regions(self.verse_cave_l, self.verse_cave_r)
self.__connect_regions(self.verse_cave_l, self.home_water)
self.__connect_regions(self.home_water, self.naija_home)
self.__connect_regions(self.home_water, self.song_cave)
self.__connect_regions(self.home_water, self.home_water_behind_rocks,
lambda state: _has_bind_song(state, self.player))
self.__connect_regions(self.home_water_behind_rocks, self.home_water_nautilus,
lambda state: _has_energy_attack_item(state, self.player))
self.__connect_regions(self.home_water, self.home_water_transturtle)
self.__connect_regions(self.home_water_behind_rocks, self.energy_temple_1)
self.__connect_regions(self.home_water_behind_rocks, self.energy_temple_altar,
lambda state: _has_energy_attack_item(state, self.player) and
_has_bind_song(state, self.player))
self.__connect_regions(self.energy_temple_1, self.energy_temple_2,
lambda state: _has_energy_form(state, self.player))
self.__connect_regions(self.energy_temple_1, self.energy_temple_idol,
lambda state: _has_fish_form(state, self.player))
self.__connect_regions(self.energy_temple_idol, self.energy_temple_boss,
lambda state: _has_energy_attack_item(state, self.player) and
_has_fish_form(state, self.player))
self.__connect_one_way_regions(self.energy_temple_1, self.energy_temple_4,
lambda state: _has_beast_form(state, self.player))
self.__connect_one_way_regions(self.energy_temple_4, self.energy_temple_1)
self.__connect_regions(self.energy_temple_4, self.energy_temple_boss,
lambda state: _has_energy_attack_item(state, self.player))
self.__connect_regions(self.energy_temple_2, self.energy_temple_3)
self.__connect_one_way_regions(self.energy_temple_3, self.energy_temple_boss,
lambda state: _has_bind_song(state, self.player) and
_has_energy_attack_item(state, self.player))
self.__connect_one_way_regions(self.energy_temple_4, self.energy_temple_blaster_room,
lambda state: _has_nature_form(state, self.player) and
_has_bind_song(state, self.player) and
_has_energy_attack_item(state, self.player))
self.__connect_regions(self.home_water, self.openwater_tl)
def __connect_open_water_regions(self) -> None:
"""
Connect entrances of the different regions around open water
"""
self.__connect_regions(self.openwater_tl, self.openwater_tr)
self.__connect_regions(self.openwater_tl, self.openwater_bl)
self.__connect_regions(self.openwater_tl, self.forest_br)
self.__connect_one_way_regions(self.openwater_tr, self.openwater_tr_turtle,
lambda state: _has_beast_form_or_arnassi_armor(state, self.player))
self.__connect_one_way_regions(self.openwater_tr_turtle, self.openwater_tr)
damaging_items_minus_nature_form = [item for item in DAMAGING_ITEMS if item != ItemNames.NATURE_FORM]
self.__connect_one_way_regions(self.openwater_tr, self.openwater_tr_urns,
lambda state: _has_bind_song(state, self.player) or
_has_damaging_item(state, self.player,
damaging_items_minus_nature_form))
self.__connect_regions(self.openwater_tr, self.openwater_br)
self.__connect_regions(self.openwater_tr, self.mithalas_city)
self.__connect_regions(self.openwater_tr, self.veil_b)
self.__connect_one_way_regions(self.openwater_tr, self.veil_br,
lambda state: _has_beast_form_or_arnassi_armor(state, self.player))
self.__connect_one_way_regions(self.veil_br, self.openwater_tr)
self.__connect_regions(self.openwater_bl, self.openwater_br)
self.__connect_regions(self.openwater_bl, self.skeleton_path)
self.__connect_regions(self.abyss_l, self.openwater_bl)
self.__connect_regions(self.skeleton_path, self.skeleton_path_sc,
lambda state: _has_spirit_form(state, self.player))
self.__connect_regions(self.abyss_r, self.openwater_br)
self.__connect_one_way_regions(self.openwater_br, self.arnassi,
lambda state: _has_beast_form(state, self.player))
self.__connect_one_way_regions(self.arnassi, self.openwater_br)
self.__connect_regions(self.arnassi, self.arnassi_cave)
self.__connect_regions(self.arnassi_cave_transturtle, self.arnassi_cave,
lambda state: _has_fish_form(state, self.player))
self.__connect_one_way_regions(self.arnassi_cave, self.arnassi_crab_boss,
lambda state: _has_beast_form_or_arnassi_armor(state, self.player) and
(_has_energy_attack_item(state, self.player) or
_has_nature_form(state, self.player)))
self.__connect_one_way_regions(self.arnassi_crab_boss, self.arnassi_cave)
def __connect_mithalas_regions(self) -> None:
"""
Connect entrances of the different regions around Mithalas
"""
self.__connect_one_way_regions(self.mithalas_city, self.mithalas_city_urns,
lambda state: _has_damaging_item(state, self.player))
self.__connect_one_way_regions(self.mithalas_city, self.mithalas_city_top_path,
lambda state: _has_beast_form_or_arnassi_armor(state, self.player))
self.__connect_one_way_regions(self.mithalas_city_top_path, self.mithalas_city)
self.__connect_regions(self.mithalas_city, self.mithalas_city_fishpass,
lambda state: _has_fish_form(state, self.player))
self.__connect_regions(self.mithalas_city, self.mithalas_castle)
self.__connect_one_way_regions(self.mithalas_city_top_path,
self.mithalas_castle_tube,
lambda state: _has_nature_form(state, self.player) and
_has_energy_attack_item(state, self.player))
self.__connect_one_way_regions(self.mithalas_castle_tube,
self.mithalas_city_top_path,
lambda state: _has_nature_form(state, self.player))
self.__connect_one_way_regions(self.mithalas_castle_tube, self.mithalas_castle_sc,
lambda state: _has_spirit_form(state, self.player))
self.__connect_one_way_regions(self.mithalas_castle_tube, self.mithalas_castle,
lambda state: _has_spirit_form(state, self.player))
self.__connect_one_way_regions(self.mithalas_castle, self.mithalas_castle_urns,
lambda state: _has_damaging_item(state, self.player))
self.__connect_regions(self.mithalas_castle, self.mithalas_castle_sc,
lambda state: _has_spirit_form(state, self.player))
self.__connect_one_way_regions(self.mithalas_castle, self.cathedral_boss_r,
lambda state: _has_beast_form(state, self.player))
self.__connect_one_way_regions(self.cathedral_boss_l, self.mithalas_castle,
lambda state: _has_beast_form(state, self.player))
self.__connect_regions(self.mithalas_castle, self.cathedral_underground,
lambda state: _has_beast_form(state, self.player))
self.__connect_regions(self.mithalas_castle, self.cathedral_top_start,
lambda state: _is_cathedral_door_opened(state, self.player))
self.__connect_one_way_regions(self.cathedral_top_start, self.cathedral_top_start_urns,
lambda state: _has_damaging_item(state, self.player))
self.__connect_regions(self.cathedral_top_start, self.cathedral_top_end,
lambda state: _has_energy_attack_item(state, self.player))
self.__connect_one_way_regions(self.cathedral_underground, self.cathedral_top_end,
lambda state: _has_beast_form(state, self.player) and
_has_damaging_item(state, self.player))
self.__connect_one_way_regions(self.cathedral_top_end, self.cathedral_underground,
lambda state: _has_energy_attack_item(state, self.player)
)
self.__connect_one_way_regions(self.cathedral_underground, self.cathedral_boss_r)
self.__connect_one_way_regions(self.cathedral_boss_r, self.cathedral_underground,
lambda state: _has_beast_form(state, self.player))
self.__connect_one_way_regions(self.cathedral_boss_r, self.cathedral_boss_l,
lambda state: _has_bind_song(state, self.player) and
_has_energy_attack_item(state, self.player))
self.__connect_one_way_regions(self.cathedral_boss_l, self.cathedral_boss_r)
def __connect_forest_regions(self) -> None:
"""
Connect entrances of the different regions around the Kelp Forest
"""
self.__connect_regions(self.forest_br, self.veil_b)
self.__connect_regions(self.forest_br, self.forest_bl)
self.__connect_one_way_regions(self.forest_bl, self.forest_bl_sc,
lambda state: _has_energy_attack_item(state, self.player) or
_has_fish_form(state, self.player))
self.__connect_one_way_regions(self.forest_bl_sc, self.forest_bl)
self.__connect_regions(self.forest_br, self.forest_tr)
self.__connect_regions(self.forest_bl, self.forest_fish_cave)
self.__connect_regions(self.forest_bl, self.forest_tl)
self.__connect_regions(self.forest_bl, self.forest_boss_entrance,
lambda state: _has_nature_form(state, self.player))
self.__connect_one_way_regions(self.forest_tl, self.forest_tl_verse_egg_room,
lambda state: _has_nature_form(state, self.player) and
_has_bind_song(state, self.player) and
_has_energy_attack_item(state, self.player) and
_has_fish_form(state, self.player))
self.__connect_one_way_regions(self.forest_tl_verse_egg_room, self.forest_tl,
lambda state: _has_fish_form(state, self.player))
self.__connect_regions(self.forest_tl, self.forest_tr)
self.__connect_regions(self.forest_tl, self.forest_boss_entrance)
self.__connect_one_way_regions(self.forest_boss_entrance, self.forest_boss,
lambda state: _has_energy_attack_item(state, self.player))
self.__connect_one_way_regions(self.forest_boss, self.forest_boss_entrance)
self.__connect_regions(self.forest_tr, self.forest_tr_fp,
lambda state: _has_fish_form(state, self.player))
self.__connect_regions(self.forest_tr, self.sprite_cave)
self.__connect_regions(self.sprite_cave, self.sprite_cave_tube,
lambda state: _has_nature_form(state, self.player))
self.__connect_regions(self.forest_tr_fp, self.mermog_cave)
self.__connect_regions(self.mermog_cave, self.mermog_boss,
lambda state: _has_beast_form(state, self.player) and
_has_energy_attack_item(state, self.player))
def __connect_veil_regions(self) -> None:
"""
Connect entrances of the different regions around The Veil
"""
self.__connect_regions(self.veil_b, self.veil_b_fp,
lambda state: _has_fish_form(state, self.player) and
_has_bind_song(state, self.player))
self.__connect_regions(self.veil_b, self.veil_b_sc,
lambda state: _has_spirit_form(state, self.player))
self.__connect_regions(self.veil_b_sc, self.veil_br,
lambda state: _has_spirit_form(state, self.player))
self.__connect_regions(self.veil_br, self.veil_tl)
self.__connect_regions(self.veil_tl, self.veil_tl_fp,
lambda state: _has_fish_form(state, self.player))
self.__connect_regions(self.veil_tl, self.veil_tr_r)
self.__connect_regions(self.veil_tl, self.turtle_cave)
self.__connect_regions(self.turtle_cave, self.turtle_cave_bubble)
self.__connect_regions(self.veil_tr_r, self.sun_temple_r)
self.__connect_one_way_regions(self.sun_temple_r, self.sun_temple_l_entrance,
lambda state: _has_sun_crystal(state, self.player) or
_has_light(state, self.player))
self.__connect_one_way_regions(self.sun_temple_l_entrance, self.sun_temple_r,
lambda state: _has_light(state, self.player))
self.__connect_regions(self.sun_temple_l_entrance, self.veil_tr_l)
self.__connect_regions(self.sun_temple_l, self.sun_temple_l_entrance)
self.__connect_regions(self.sun_temple_l, self.sun_temple_boss_path)
self.__connect_regions(self.sun_temple_boss_path, self.sun_temple_boss,
lambda state: _has_energy_attack_item(state, self.player))
self.__connect_one_way_regions(self.sun_temple_boss, self.veil_tr_l)
self.__connect_regions(self.veil_tr_l, self.veil_tr_l_fp,
lambda state: _has_fish_form(state, self.player))
self.__connect_one_way_regions(self.veil_tr_l_fp, self.octo_cave_t,
lambda state: _has_sun_form(state, self.player) and
_has_beast_form(state, self.player) and
_has_energy_attack_item(state, self.player))
self.__connect_one_way_regions(self.octo_cave_t, self.veil_tr_l_fp)
self.__connect_regions(self.veil_tr_l_fp, self.octo_cave_b)
def __connect_abyss_regions(self) -> None:
"""
Connect entrances of the different regions around The Abyss
"""
self.__connect_regions(self.abyss_l, self.abyss_lb,
lambda state: _has_nature_form(state, self.player))
self.__connect_regions(self.abyss_lb, self.sunken_city_r,
lambda state: _has_li(state, self.player))
self.__connect_one_way_regions(self.abyss_lb, self.body_c,
lambda state: _has_tongue_cleared(state, self.player))
self.__connect_one_way_regions(self.body_c, self.abyss_lb)
self.__connect_one_way_regions(self.abyss_l, self.king_jellyfish_cave,
lambda state: _has_dual_form(state, self.player) or
(_has_energy_form(state, self.player) and
_has_beast_form(state, self.player)))
self.__connect_one_way_regions(self.king_jellyfish_cave, self.abyss_l)
self.__connect_regions(self.abyss_l, self.abyss_r)
self.__connect_regions(self.abyss_r, self.abyss_r_whale,
lambda state: _has_spirit_form(state, self.player) and
_has_sun_form(state, self.player))
self.__connect_regions(self.abyss_r_whale, self.whale)
self.__connect_regions(self.abyss_r, self.abyss_r_transturtle)
self.__connect_regions(self.abyss_r, self.first_secret,
lambda state: _has_spirit_form(state, self.player) and
_has_sun_form(state, self.player) and
_has_bind_song(state, self.player) and
_has_energy_attack_item(state, self.player))
self.__connect_regions(self.abyss_r, self.ice_cave,
lambda state: _has_spirit_form(state, self.player))
self.__connect_regions(self.ice_cave, self.frozen_feil)
self.__connect_one_way_regions(self.frozen_feil, self.bubble_cave,
lambda state: _has_beast_form(state, self.player) or
_has_hot_soup(state, self.player))
self.__connect_one_way_regions(self.bubble_cave, self.frozen_feil)
self.__connect_one_way_regions(self.bubble_cave, self.bubble_cave_boss,
lambda state: _has_nature_form(state, self.player) and
_has_bind_song(state, self.player)
)
self.__connect_one_way_regions(self.bubble_cave_boss, self.bubble_cave)
def __connect_sunken_city_regions(self) -> None:
"""
Connect entrances of the different regions around The Sunken City
"""
self.__connect_regions(self.sunken_city_r, self.sunken_city_l)
self.__connect_one_way_regions(self.sunken_city_r, self.sunken_city_r_crates,
lambda state: _has_energy_attack_item(state, self.player))
self.__connect_regions(self.sunken_city_l, self.sunken_city_l_bedroom,
lambda state: _has_spirit_form(state, self.player))
self.__connect_one_way_regions(self.sunken_city_l, self.sunken_city_l_crates,
lambda state: _has_energy_attack_item(state, self.player))
self.__connect_regions(self.sunken_city_l, self.sunken_city_boss,
lambda state: _has_beast_form(state, self.player) and
_has_sun_form(state, self.player) and
_has_energy_attack_item(state, self.player) and
_has_bind_song(state, self.player))
def __connect_body_regions(self) -> None:
"""
Connect entrances of the different regions around The Body
"""
self.__connect_one_way_regions(self.body_c, self.body_l,
lambda state: _has_energy_form(state, self.player))
self.__connect_one_way_regions(self.body_l, self.body_c)
self.__connect_regions(self.body_c, self.body_rt)
self.__connect_one_way_regions(self.body_c, self.body_rb,
lambda state: _has_energy_form(state, self.player))
self.__connect_one_way_regions(self.body_rb, self.body_c)
self.__connect_regions(self.body_c, self.body_b,
lambda state: _has_dual_form(state, self.player))
self.__connect_regions(self.body_b, self.final_boss_lobby,
lambda state: _has_dual_form(state, self.player))
self.__connect_regions(self.final_boss_lobby, self.final_boss_tube,
lambda state: _has_nature_form(state, self.player))
self.__connect_one_way_regions(self.final_boss_lobby, self.final_boss,
lambda state: _has_energy_form(state, self.player) and
_has_dual_form(state, self.player) and
_has_sun_form(state, self.player) and
_has_bind_song(state, self.player))
self.__connect_one_way_regions(self.final_boss, self.final_boss_end)
def __connect_four_gods_end(self, options: AquariaOptions) -> None:
"""
Connect an entrance for the four gods objective ending
"""
if options.mini_bosses_to_beat.value > 6:
victory_lambda = lambda state: (_has_four_gods_beated(state, self.player) and
_has_mini_bosses(state, self.player))
elif options.big_bosses_to_beat.value > 0:
victory_lambda = lambda state: (_has_four_gods_beated(state, self.player) and
_has_mini_bosses_four_gods(state, self.player))
else:
victory_lambda = lambda state: _has_four_gods_beated(state, self.player)
self.__connect_one_way_regions(self.menu, self.four_gods_end, victory_lambda)
def __connect_transturtle(self, item_target: str, region_source: Region, region_target: Region) -> None:
"""Connect a single transturtle to another one"""
if region_source != region_target:
self.__connect_one_way_regions(region_source, region_target,
lambda state: state.has(item_target, self.player))
def _connect_transturtle_to_other(self, region: Region) -> None:
"""Connect a single transturtle to all others"""
self.__connect_transturtle(ItemNames.TRANSTURTLE_VEIL_TOP_LEFT, region, self.veil_tl)
self.__connect_transturtle(ItemNames.TRANSTURTLE_VEIL_TOP_RIGHT, region, self.veil_tr_l)
self.__connect_transturtle(ItemNames.TRANSTURTLE_OPEN_WATERS, region, self.openwater_tr_turtle)
self.__connect_transturtle(ItemNames.TRANSTURTLE_KELP_FOREST, region, self.forest_bl)
self.__connect_transturtle(ItemNames.TRANSTURTLE_HOME_WATERS, region, self.home_water_transturtle)
self.__connect_transturtle(ItemNames.TRANSTURTLE_SIMON_SAYS, region, self.simon)
self.__connect_transturtle(ItemNames.TRANSTURTLE_ARNASSI_RUINS, region, self.arnassi_cave_transturtle)
self.__connect_transturtle(ItemNames.TRANSTURTLE_ABYSS, region, self.abyss_r_transturtle)
self.__connect_transturtle(ItemNames.TRANSTURTLE_BODY, region, self.final_boss_tube)
def __connect_transturtles(self) -> None:
"""Connect every transturtle with others"""
self._connect_transturtle_to_other(self.veil_tl)
self._connect_transturtle_to_other(self.veil_tr_l)
self._connect_transturtle_to_other(self.openwater_tr_turtle)
self._connect_transturtle_to_other(self.forest_bl)
self._connect_transturtle_to_other(self.home_water_transturtle)
self._connect_transturtle_to_other(self.simon)
self._connect_transturtle_to_other(self.arnassi_cave_transturtle)
self._connect_transturtle_to_other(self.abyss_r_transturtle)
self._connect_transturtle_to_other(self.final_boss_tube)
def connect_regions(self, options: AquariaOptions) -> None:
"""
Connect every region (entrances and exits)
"""
self.__connect_home_water_regions()
self.__connect_open_water_regions()
self.__connect_mithalas_regions()
self.__connect_forest_regions()
self.__connect_veil_regions()
self.__connect_abyss_regions()
self.__connect_sunken_city_regions()
self.__connect_body_regions()
if self.is_four_gods:
self.__connect_four_gods_end(options)
self.__connect_transturtles()
def __add_event_location(self, region: Region, name: str, event_name: str) -> None:
"""
Add an event to the `region` with the name `name` and the item
`event_name`
"""
location: AquariaLocation = AquariaLocation(
self.player, name, None, region
)
region.locations.append(location)
location.place_locked_item(AquariaItem(event_name,
ItemClassification.progression,
None,
self.player))
def __add_event_big_bosses(self) -> None:
"""
Add every bit bosses (other than the creator) events to the `world`
"""
self.__add_event_location(self.energy_temple_boss,
AquariaLocationNames.BEATING_FALLEN_GOD,
ItemNames.FALLEN_GOD_BEATED)
self.__add_event_location(self.cathedral_boss_l,
AquariaLocationNames.BEATING_MITHALAN_GOD,
ItemNames.MITHALAN_GOD_BEATED)
self.__add_event_location(self.forest_boss,
AquariaLocationNames.BEATING_DRUNIAN_GOD,
ItemNames.DRUNIAN_GOD_BEATED)
self.__add_event_location(self.sun_temple_boss,
AquariaLocationNames.BEATING_LUMEREAN_GOD,
ItemNames.LUMEREAN_GOD_BEATED)
self.__add_event_location(self.sunken_city_boss,
AquariaLocationNames.BEATING_THE_GOLEM,
ItemNames.THE_GOLEM_BEATED)
def __add_event_mini_bosses(self) -> None:
"""
Add every mini bosses (excluding Energy Statue and Simon Says)
events to the `world`
"""
self.__add_event_location(self.home_water_nautilus,
AquariaLocationNames.BEATING_NAUTILUS_PRIME,
ItemNames.NAUTILUS_PRIME_BEATED)
self.__add_event_location(self.energy_temple_blaster_room,
AquariaLocationNames.BEATING_BLASTER_PEG_PRIME,
ItemNames.BLASTER_PEG_PRIME_BEATED)
self.__add_event_location(self.mermog_boss,
AquariaLocationNames.BEATING_MERGOG,
ItemNames.MERGOG_BEATED)
self.__add_event_location(self.mithalas_castle_tube,
AquariaLocationNames.BEATING_MITHALAN_PRIESTS,
ItemNames.MITHALAN_PRIESTS_BEATED)
self.__add_event_location(self.octo_cave_t,
AquariaLocationNames.BEATING_OCTOPUS_PRIME,
ItemNames.OCTOPUS_PRIME_BEATED)
self.__add_event_location(self.arnassi_crab_boss,
AquariaLocationNames.BEATING_CRABBIUS_MAXIMUS,
ItemNames.CRABBIUS_MAXIMUS_BEATED)
self.__add_event_location(self.bubble_cave_boss,
AquariaLocationNames.BEATING_MANTIS_SHRIMP_PRIME,
ItemNames.MANTIS_SHRIMP_PRIME_BEATED)
self.__add_event_location(self.king_jellyfish_cave,
AquariaLocationNames.BEATING_KING_JELLYFISH_GOD_PRIME,
ItemNames.KING_JELLYFISH_GOD_PRIME_BEATED)
def __add_event_secrets(self) -> None:
"""
Add secrets events to the `world`
"""
self.__add_event_location(self.first_secret,
# Doit ajouter une région pour le AquariaLocationNames.FIRST_SECRET
AquariaLocationNames.FIRST_SECRET,
ItemNames.FIRST_SECRET_OBTAINED)
self.__add_event_location(self.mithalas_city,
AquariaLocationNames.SECOND_SECRET,
ItemNames.SECOND_SECRET_OBTAINED)
self.__add_event_location(self.sun_temple_l,
AquariaLocationNames.THIRD_SECRET,
ItemNames.THIRD_SECRET_OBTAINED)
def add_event_locations(self, options: AquariaOptions) -> None:
"""
Add every event (locations and items) to the `world`
"""
self.__add_event_mini_bosses()
self.__add_event_location(self.sun_temple_r,
AquariaLocationNames.SUN_CRYSTAL,
ItemNames.HAS_SUN_CRYSTAL)
self.__add_event_big_bosses()
self.__add_event_location(self.sunken_city_boss,
AquariaLocationNames.SUNKEN_CITY_CLEARED,
ItemNames.BODY_TONGUE_CLEARED)
if self.is_four_gods:
self.__add_event_location(self.four_gods_end, AquariaLocationNames.OBJECTIVE_COMPLETE,
ItemNames.VICTORY)
else:
self.__add_event_secrets()
self.__add_event_location(self.final_boss_end, AquariaLocationNames.OBJECTIVE_COMPLETE,
ItemNames.VICTORY)
def __adjusting_soup_rules(self) -> None:
"""
Modify rules for location that need soup
"""
add_rule(self.multiworld.get_location(AquariaLocationNames.TURTLE_CAVE_URCHIN_COSTUME, self.player),
lambda state: _has_hot_soup(state, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_FIRST_CLIFF_BULB, self.player),
lambda state: _has_beast_and_soup_form(state, self.player) or
state.has(ItemNames.LUMEREAN_GOD_BEATED, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_SECOND_CLIFF_BULB, self.player),
lambda state: _has_beast_and_soup_form(state, self.player) or
state.has(ItemNames.LUMEREAN_GOD_BEATED, self.player))
add_rule(
self.multiworld.get_location(AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_BULB_AT_THE_TOP_OF_THE_WATERFALL,
self.player),
lambda state: _has_beast_and_soup_form(state, self.player))
def __adjusting_under_rock_location(self, options: AquariaOptions) -> None:
"""
Modify rules implying bind song needed for bulb under rocks
"""
add_rule(self.multiworld.get_location(
AquariaLocationNames.HOME_WATERS_BULB_UNDER_THE_ROCK_IN_THE_LEFT_PATH_FROM_THE_VERSE_CAVE,
self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(
AquariaLocationNames.VERSE_CAVE_LEFT_AREA_BULB_UNDER_THE_ROCK_AT_THE_END_OF_THE_PATH,
self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(
AquariaLocationNames.NAIJA_S_HOME_BULB_UNDER_THE_ROCK_AT_THE_RIGHT_OF_THE_MAIN_PATH,
self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(
AquariaLocationNames.SONG_CAVE_BULB_UNDER_THE_ROCK_IN_THE_PATH_TO_THE_SINGING_STATUES,
self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.SONG_CAVE_BULB_UNDER_THE_ROCK_CLOSE_TO_THE_SONG_DOOR,
self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.ENERGY_TEMPLE_SECOND_AREA_BULB_UNDER_THE_ROCK,
self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(
AquariaLocationNames.OPEN_WATERS_TOP_LEFT_AREA_BULB_UNDER_THE_ROCK_IN_THE_RIGHT_PATH,
self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(
AquariaLocationNames.OPEN_WATERS_TOP_LEFT_AREA_BULB_UNDER_THE_ROCK_IN_THE_LEFT_PATH,
self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_UNDER_THE_ROCK_IN_THE_RIGHT_PATH,
self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_BULB_UNDER_THE_ROCK_IN_THE_TOP_RIGHT_PATH,
self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_BULB_UNDER_THE_ROCK_IN_THE_TOP_RIGHT_PATH,
self.player), lambda state: _has_bind_song(state, self.player))
if not self.is_four_gods:
add_rule(self.multiworld.get_location(
AquariaLocationNames.ABYSS_RIGHT_AREA_BULB_BEHIND_THE_ROCK_IN_THE_WHALE_ROOM,
self.player), lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.ABYSS_RIGHT_AREA_BULB_IN_THE_MIDDLE_PATH,
self.player), lambda state: _has_bind_song(state, self.player))
def __adjusting_light_in_dark_place_rules(self, light_option: LightNeededToGetToDarkPlaces) -> None:
"""
Modify rules implying that the player needs a light to go in dark places
"""
if light_option == LightNeededToGetToDarkPlaces.option_sun_form:
light_lambda = _has_sun_form
else:
light_lambda = _has_light
add_rule(self.multiworld.get_location(AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BLACK_PEARL, self.player),
lambda state: light_lambda(state, self.player))
add_rule(
self.multiworld.get_location(AquariaLocationNames.KELP_FOREST_BOTTOM_RIGHT_AREA_ODD_CONTAINER, self.player),
lambda state: light_lambda(state, self.player))
add_rule(self.multiworld.get_entrance(self.get_entrance_name(self.sun_temple_l_entrance, self.sun_temple_l),
self.player), lambda state: _has_light(state, self.player) or
_has_sun_crystal(state, self.player))
add_rule(self.multiworld.get_entrance(self.get_entrance_name(self.sun_temple_boss_path, self.sun_temple_l),
self.player), lambda state: _has_light(state, self.player) or
_has_sun_crystal(state, self.player))
add_rule(self.multiworld.get_entrance(self.get_entrance_name(self.abyss_r_transturtle, self.abyss_r),
self.player),
lambda state: light_lambda(state, self.player))
add_rule(self.multiworld.get_entrance(self.get_entrance_name(self.body_c, self.abyss_lb), self.player),
lambda state: light_lambda(state, self.player))
add_rule(self.multiworld.get_entrance(self.get_entrance_name(self.openwater_br, self.abyss_r), self.player),
lambda state: light_lambda(state, self.player))
add_rule(self.multiworld.get_entrance(self.get_entrance_name(self.openwater_bl, self.abyss_l), self.player),
lambda state: light_lambda(state, self.player))
def __adjusting_manual_rules(self, options: AquariaOptions) -> None:
add_rule(self.multiworld.get_location(AquariaLocationNames.MITHALAS_CATHEDRAL_MITHALAN_DRESS, self.player),
lambda state: _has_beast_form(state, self.player))
add_rule(self.multiworld.get_location(
AquariaLocationNames.OPEN_WATERS_BOTTOM_LEFT_AREA_BULB_INSIDE_THE_LOWEST_FISH_PASS, self.player),
lambda state: _has_fish_form(state, self.player))
add_rule(
self.multiworld.get_location(AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_WALKER_BABY, self.player),
lambda state: _has_spirit_form(state, self.player))
add_rule(
self.multiworld.get_location(
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_BULB_HIDDEN_BEHIND_THE_BLOCKING_ROCK, self.player),
lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.TURTLE_CAVE_TURTLE_EGG, self.player),
lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.SONG_CAVE_ANEMONE_SEED, self.player),
lambda state: _has_nature_form(state, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.SONG_CAVE_VERSE_EGG, self.player),
lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.VERSE_CAVE_RIGHT_AREA_BIG_SEED, self.player),
lambda state: _has_bind_song(state, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.ARNASSI_RUINS_SONG_PLANT_SPORE, self.player),
lambda state: _has_beast_form_or_arnassi_armor(state, self.player))
add_rule(self.multiworld.get_location(
AquariaLocationNames.ENERGY_TEMPLE_FIRST_AREA_BULB_IN_THE_BOTTOM_ROOM_BLOCKED_BY_A_ROCK,
self.player), lambda state: _has_bind_song(state, self.player))
add_rule(
self.multiworld.get_location(AquariaLocationNames.NAIJA_S_HOME_BULB_AFTER_THE_ENERGY_DOOR, self.player),
lambda state: _has_energy_attack_item(state, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.ARNASSI_RUINS_ARNASSI_ARMOR, self.player),
lambda state: _has_fish_form(state, self.player) or
_has_beast_and_soup_form(state, self.player))
add_rule(
self.multiworld.get_location(AquariaLocationNames.MITHALAS_CITY_URN_INSIDE_A_HOME_FISH_PASS, self.player),
lambda state: _has_damaging_item(state, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.MITHALAS_CITY_URN_IN_THE_CASTLE_FLOWER_TUBE_ENTRANCE,
self.player),
lambda state: _has_damaging_item(state, self.player))
add_rule(self.multiworld.get_location(
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_BULB_IN_THE_MIDDLE_OF_THE_WALL_JUMP_CLIFF, self.player
), lambda state: _has_beast_form_or_arnassi_armor(state, self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_JELLY_EGG, self.player),
lambda state: _has_beast_form(state, self.player))
add_rule(self.multiworld.get_location(
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_BULB_IN_THE_SMALL_PATH_BEFORE_MITHALAS,
self.player), lambda state: _has_bind_song(state, self.player)
)
add_rule(self.multiworld.get_location(AquariaLocationNames.SITTING_ON_THRONE, self.player),
lambda state: _has_bind_song(state, self.player))
if not self.is_four_gods:
add_rule(self.multiworld.get_location(AquariaLocationNames.ABYSS_LEFT_AREA_BULB_IN_THE_BOTTOM_FISH_PASS,
self.player),
lambda state: _has_fish_form(state, self.player))
add_rule(
self.multiworld.get_location(AquariaLocationNames.THE_BODY_CENTER_AREA_BREAKING_LI_S_CAGE, self.player),
lambda state: _has_tongue_cleared(state, self.player))
def __no_progression_hard_or_hidden_location(self, options: AquariaOptions) -> None:
self.multiworld.get_location(AquariaLocationNames.ENERGY_TEMPLE_BOSS_AREA_FALLEN_GOD_TOOTH,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.MITHALAS_BOSS_AREA_BEATING_MITHALAN_GOD,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.KELP_FOREST_BOSS_AREA_BEATING_DRUNIAN_GOD,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.SUN_TEMPLE_BOSS_AREA_BEATING_LUMEREAN_GOD,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.HOME_WATERS_NAUTILUS_EGG,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.ENERGY_TEMPLE_BLASTER_ROOM_BLASTER_EGG,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.MITHALAS_CITY_CASTLE_BEATING_THE_PRIESTS,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.MERMOG_CAVE_PIRANHA_EGG,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.OCTOPUS_CAVE_DUMBO_EGG,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_FIRST_CLIFF_BULB,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_SECOND_CLIFF_BULB,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_BULB_AT_THE_TOP_OF_THE_WATERFALL,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_BULB_CLOSE_TO_THE_SPIRIT_CRYSTALS,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_WALKER_BABY,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.SUN_TEMPLE_SUN_KEY,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.SUN_TEMPLE_BULB_IN_THE_HIDDEN_ROOM_OF_THE_RIGHT_PART,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.ARNASSI_RUINS_ARNASSI_ARMOR,
self.player).item_rule = _item_not_advancement
if not self.is_four_gods:
self.multiworld.get_location(AquariaLocationNames.SUNKEN_CITY_BULB_ON_TOP_OF_THE_BOSS_AREA,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.THE_BODY_BOTTOM_AREA_MUTANT_COSTUME,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.FINAL_BOSS_AREA_BULB_IN_THE_BOSS_THIRD_FORM_ROOM,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(
AquariaLocationNames.KING_JELLYFISH_CAVE_BULB_IN_THE_RIGHT_PATH_FROM_KING_JELLY,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.KING_JELLYFISH_CAVE_JELLYFISH_COSTUME,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.BUBBLE_CAVE_BULB_IN_THE_LEFT_CAVE_WALL,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(
AquariaLocationNames.BUBBLE_CAVE_BULB_IN_THE_RIGHT_CAVE_WALL_BEHIND_THE_ICE_CRYSTAL,
self.player).item_rule = _item_not_advancement
self.multiworld.get_location(AquariaLocationNames.BUBBLE_CAVE_VERSE_EGG,
self.player).item_rule = _item_not_advancement
def __no_progression_area(self, area: dict) -> None:
"""Be sure to not put any progression items in location of an `area`"""
for location in area:
self.multiworld.get_location(location, self.player).item_rule = _item_not_advancement
def __no_progression_kelp_forest(self) -> None:
"""Be sure to not put any progression items in Kelp forest"""
self.__no_progression_area(AquariaLocations.locations_forest_tl)
self.__no_progression_area(AquariaLocations.locations_forest_tl_verse_egg_room)
self.__no_progression_area(AquariaLocations.locations_forest_tr)
self.__no_progression_area(AquariaLocations.locations_forest_tr_fp)
self.__no_progression_area(AquariaLocations.locations_forest_bl)
self.__no_progression_area(AquariaLocations.locations_forest_bl_sc)
self.__no_progression_area(AquariaLocations.locations_forest_br)
self.__no_progression_area(AquariaLocations.locations_forest_boss)
self.__no_progression_area(AquariaLocations.locations_forest_boss_entrance)
self.__no_progression_area(AquariaLocations.locations_forest_fish_cave)
self.__no_progression_area(AquariaLocations.locations_sprite_cave)
self.__no_progression_area(AquariaLocations.locations_sprite_cave_tube)
self.__no_progression_area(AquariaLocations.locations_mermog_cave)
self.__no_progression_area(AquariaLocations.locations_mermog_boss)
def __no_progression_veil(self) -> None:
"""Be sure to not put any progression items in The Veil"""
self.__no_progression_area(AquariaLocations.locations_veil_tl)
self.__no_progression_area(AquariaLocations.locations_veil_tl_fp)
self.__no_progression_area(AquariaLocations.locations_turtle_cave)
self.__no_progression_area(AquariaLocations.locations_turtle_cave_bubble)
self.__no_progression_area(AquariaLocations.locations_veil_tr_r)
self.__no_progression_area(AquariaLocations.locations_veil_tr_l)
self.__no_progression_area(AquariaLocations.locations_veil_b)
self.__no_progression_area(AquariaLocations.locations_veil_b_sc)
self.__no_progression_area(AquariaLocations.locations_veil_b_fp)
self.__no_progression_area(AquariaLocations.locations_veil_br)
self.__no_progression_area(AquariaLocations.locations_octo_cave_t)
self.__no_progression_area(AquariaLocations.locations_octo_cave_b)
self.__no_progression_area(AquariaLocations.locations_sun_temple_l)
self.__no_progression_area(AquariaLocations.locations_sun_temple_r)
self.__no_progression_area(AquariaLocations.locations_sun_temple_boss_path)
self.__no_progression_area(AquariaLocations.locations_sun_temple_boss)
def __no_progression_mithalas(self) -> None:
"""Be sure to not put any progression items in Mithalas"""
self.__no_progression_area(AquariaLocations.locations_mithalas_city)
self.__no_progression_area(AquariaLocations.locations_mithalas_city_urns)
self.__no_progression_area(AquariaLocations.locations_mithalas_city_top_path)
self.__no_progression_area(AquariaLocations.locations_mithalas_city_fishpass)
self.__no_progression_area(AquariaLocations.locations_mithalas_castle)
self.__no_progression_area(AquariaLocations.locations_mithalas_castle_urns)
self.__no_progression_area(AquariaLocations.locations_mithalas_castle_tube)
self.__no_progression_area(AquariaLocations.locations_mithalas_castle_sc)
self.__no_progression_area(AquariaLocations.locations_cathedral_top_start)
self.__no_progression_area(AquariaLocations.locations_cathedral_top_start_urns)
self.__no_progression_area(AquariaLocations.locations_cathedral_top_end)
self.__no_progression_area(AquariaLocations.locations_cathedral_underground)
self.__no_progression_area(AquariaLocations.locations_cathedral_boss)
def __no_progression_energy_temple(self) -> None:
"""Be sure to not put any progression items in the Energy Temple"""
self.__no_progression_area(AquariaLocations.locations_energy_temple_1)
self.__no_progression_area(AquariaLocations.locations_energy_temple_idol)
self.__no_progression_area(AquariaLocations.locations_energy_temple_2)
self.__no_progression_area(AquariaLocations.locations_energy_temple_altar)
self.__no_progression_area(AquariaLocations.locations_energy_temple_3)
self.__no_progression_area(AquariaLocations.locations_energy_temple_boss)
self.__no_progression_area(AquariaLocations.locations_energy_temple_blaster_room)
def __no_progression_arnassi_ruins(self, options: AquariaOptions) -> None:
"""Be sure to not put any progression items in the Arnassi ruins"""
self.__no_progression_area(AquariaLocations.locations_arnassi)
self.__no_progression_area(AquariaLocations.locations_arnassi_cave)
self.__no_progression_area(AquariaLocations.locations_arnassi_cave_transturtle)
self.__no_progression_area(AquariaLocations.locations_arnassi_crab_boss)
if options.turtle_randomizer == 0:
self.__no_progression_area(AquariaLocations.locations_simon)
def __no_progression_frozen_veil(self) -> None:
"""Be sure to not put any progression items in the Frozen Veil"""
self.__no_progression_area(AquariaLocations.locations_ice_cave)
self.__no_progression_area(AquariaLocations.locations_bubble_cave)
self.__no_progression_area(AquariaLocations.locations_bubble_cave_boss)
def __no_progression_abyss(self) -> None:
"""Be sure to not put any progression items in the Abyss"""
self.__no_progression_area(AquariaLocations.locations_abyss_l)
self.__no_progression_area(AquariaLocations.locations_abyss_lb)
self.__no_progression_area(AquariaLocations.locations_abyss_r)
self.__no_progression_area(AquariaLocations.locations_abyss_r_whale)
self.__no_progression_area(AquariaLocations.locations_abyss_r_transturtle)
self.__no_progression_area(AquariaLocations.locations_king_jellyfish_cave)
def __no_progression_sunken_city(self) -> None:
"""Be sure to not put any progression items in the Sunken City"""
self.__no_progression_area(AquariaLocations.locations_sunken_city_r)
self.__no_progression_area(AquariaLocations.locations_sunken_city_l)
self.__no_progression_area(AquariaLocations.locations_sunken_city_l_bedroom)
self.__no_progression_area(AquariaLocations.locations_sunken_city_boss)
def __no_progression_body(self) -> None:
"""Be sure to not put any progression items in the Body"""
self.__no_progression_area(AquariaLocations.locations_body_c)
self.__no_progression_area(AquariaLocations.locations_body_l)
self.__no_progression_area(AquariaLocations.locations_body_rt)
self.__no_progression_area(AquariaLocations.locations_body_rb)
self.__no_progression_area(AquariaLocations.locations_body_b)
self.__no_progression_area(AquariaLocations.locations_final_boss_tube)
self.__no_progression_area(AquariaLocations.locations_final_boss)
def __no_progression_areas(self, options: AquariaOptions) -> None:
"""Manage options that remove progression items from areas around the Aquaria world"""
if options.no_progression_simon_says:
self.__no_progression_area(AquariaLocations.locations_simon)
if options.no_progression_kelp_forest:
self.__no_progression_kelp_forest()
if options.no_progression_veil:
self.__no_progression_veil()
if options.no_progression_mithalas:
self.__no_progression_mithalas()
if options.no_progression_energy_temple:
self.__no_progression_energy_temple()
if options.no_progression_arnassi_ruins:
self.__no_progression_arnassi_ruins(options)
if not self.is_four_gods:
if options.no_progression_frozen_veil:
self.__no_progression_frozen_veil()
if options.no_progression_abyss:
self.__no_progression_abyss()
if options.no_progression_sunken_city:
self.__no_progression_sunken_city()
if options.no_progression_body:
self.__no_progression_body()
def adjusting_rules(self, options: AquariaOptions) -> None:
"""
Modify rules for single location or optional rules
"""
self.__adjusting_manual_rules(options)
self.__adjusting_soup_rules()
self.__no_progression_areas(options)
if options.light_needed_to_get_to_dark_places != LightNeededToGetToDarkPlaces.option_off:
self.__adjusting_light_in_dark_place_rules(options.light_needed_to_get_to_dark_places)
if options.bind_song_needed_to_get_under_rock_bulb:
self.__adjusting_under_rock_location(options)
if not self.is_four_gods:
if options.mini_bosses_to_beat.value > 0:
add_rule(self.multiworld.get_entrance(self.get_entrance_name(self.final_boss_lobby, self.final_boss),
self.player), lambda state: _has_mini_bosses(state, self.player))
if options.big_bosses_to_beat.value > 0:
add_rule(self.multiworld.get_entrance(self.get_entrance_name(self.final_boss_lobby, self.final_boss),
self.player), lambda state: _has_big_bosses(state, self.player))
if options.objective.value == options.objective.option_obtain_secrets_and_kill_the_creator:
add_rule(self.multiworld.get_entrance(self.get_entrance_name(self.final_boss_lobby, self.final_boss),
self.player), lambda state: _has_secrets(state, self.player))
if (options.unconfine_home_water.value == UnconfineHomeWater.option_via_energy_door or
options.unconfine_home_water.value == UnconfineHomeWater.option_off):
add_rule(self.multiworld.get_entrance(self.get_entrance_name(self.home_water, self.home_water_transturtle),
self.player), lambda state: _has_bind_song(state, self.player))
if (options.unconfine_home_water.value == UnconfineHomeWater.option_via_transturtle or
options.unconfine_home_water.value == UnconfineHomeWater.option_off):
add_rule(self.multiworld.get_entrance(self.get_entrance_name(self.home_water, self.openwater_tl),
self.player),
lambda state: _has_bind_song(state, self.player) and
_has_energy_attack_item(state, self.player))
if options.no_progression_hard_or_hidden_locations:
self.__no_progression_hard_or_hidden_location(options)
def __add_home_water_regions_to_world(self) -> None:
"""
Add every region around home water to the `world`
"""
self.multiworld.regions.append(self.menu)
self.multiworld.regions.append(self.verse_cave_r)
self.multiworld.regions.append(self.verse_cave_l)
self.multiworld.regions.append(self.home_water)
self.multiworld.regions.append(self.home_water_nautilus)
self.multiworld.regions.append(self.home_water_transturtle)
self.multiworld.regions.append(self.naija_home)
self.multiworld.regions.append(self.song_cave)
self.multiworld.regions.append(self.energy_temple_1)
self.multiworld.regions.append(self.energy_temple_2)
self.multiworld.regions.append(self.energy_temple_3)
self.multiworld.regions.append(self.energy_temple_boss)
self.multiworld.regions.append(self.energy_temple_blaster_room)
self.multiworld.regions.append(self.energy_temple_altar)
def __add_open_water_regions_to_world(self) -> None:
"""
Add every region around open water to the `world`
"""
self.multiworld.regions.append(self.openwater_tl)
self.multiworld.regions.append(self.openwater_tr)
self.multiworld.regions.append(self.openwater_tr_turtle)
self.multiworld.regions.append(self.openwater_bl)
self.multiworld.regions.append(self.openwater_br)
self.multiworld.regions.append(self.skeleton_path)
self.multiworld.regions.append(self.skeleton_path_sc)
self.multiworld.regions.append(self.arnassi)
self.multiworld.regions.append(self.arnassi_cave)
self.multiworld.regions.append(self.arnassi_cave_transturtle)
self.multiworld.regions.append(self.arnassi_crab_boss)
self.multiworld.regions.append(self.simon)
def __add_mithalas_regions_to_world(self) -> None:
"""
Add every region around Mithalas to the `world`
"""
self.multiworld.regions.append(self.mithalas_city)
self.multiworld.regions.append(self.mithalas_city_top_path)
self.multiworld.regions.append(self.mithalas_city_fishpass)
self.multiworld.regions.append(self.mithalas_castle)
self.multiworld.regions.append(self.mithalas_castle_tube)
self.multiworld.regions.append(self.mithalas_castle_sc)
self.multiworld.regions.append(self.cathedral_top_start)
self.multiworld.regions.append(self.cathedral_top_start_urns)
self.multiworld.regions.append(self.cathedral_top_end)
self.multiworld.regions.append(self.cathedral_underground)
self.multiworld.regions.append(self.cathedral_boss_l)
self.multiworld.regions.append(self.cathedral_boss_r)
def __add_forest_regions_to_world(self) -> None:
"""
Add every region around the kelp forest to the `world`
"""
self.multiworld.regions.append(self.forest_tl)
self.multiworld.regions.append(self.forest_tl_verse_egg_room)
self.multiworld.regions.append(self.forest_tr)
self.multiworld.regions.append(self.forest_tr_fp)
self.multiworld.regions.append(self.forest_bl)
self.multiworld.regions.append(self.forest_bl_sc)
self.multiworld.regions.append(self.forest_br)
self.multiworld.regions.append(self.forest_boss)
self.multiworld.regions.append(self.forest_boss_entrance)
self.multiworld.regions.append(self.sprite_cave)
self.multiworld.regions.append(self.sprite_cave_tube)
self.multiworld.regions.append(self.mermog_cave)
self.multiworld.regions.append(self.mermog_boss)
self.multiworld.regions.append(self.forest_fish_cave)
def __add_veil_regions_to_world(self) -> None:
"""
Add every region around the Veil to the `world`
"""
self.multiworld.regions.append(self.veil_tl)
self.multiworld.regions.append(self.veil_tl_fp)
self.multiworld.regions.append(self.veil_tr_l)
self.multiworld.regions.append(self.veil_tr_l_fp)
self.multiworld.regions.append(self.veil_tr_r)
self.multiworld.regions.append(self.veil_b)
self.multiworld.regions.append(self.veil_b_sc)
self.multiworld.regions.append(self.veil_b_fp)
self.multiworld.regions.append(self.veil_br)
self.multiworld.regions.append(self.octo_cave_t)
self.multiworld.regions.append(self.octo_cave_b)
self.multiworld.regions.append(self.turtle_cave)
self.multiworld.regions.append(self.turtle_cave_bubble)
self.multiworld.regions.append(self.sun_temple_l)
self.multiworld.regions.append(self.sun_temple_l_entrance)
self.multiworld.regions.append(self.sun_temple_r)
self.multiworld.regions.append(self.sun_temple_boss_path)
self.multiworld.regions.append(self.sun_temple_boss)
def __add_abyss_regions_to_world(self) -> None:
"""
Add every region around the Abyss to the `world`
"""
self.multiworld.regions.append(self.abyss_l)
self.multiworld.regions.append(self.abyss_lb)
self.multiworld.regions.append(self.abyss_r)
self.multiworld.regions.append(self.abyss_r_whale)
self.multiworld.regions.append(self.abyss_r_transturtle)
self.multiworld.regions.append(self.ice_cave)
self.multiworld.regions.append(self.bubble_cave)
self.multiworld.regions.append(self.bubble_cave_boss)
self.multiworld.regions.append(self.king_jellyfish_cave)
self.multiworld.regions.append(self.whale)
self.multiworld.regions.append(self.sunken_city_l)
self.multiworld.regions.append(self.sunken_city_r)
self.multiworld.regions.append(self.sunken_city_boss)
self.multiworld.regions.append(self.sunken_city_l_bedroom)
def __add_body_regions_to_world(self) -> None:
"""
Add every region around the Body to the `world`
"""
self.multiworld.regions.append(self.body_c)
self.multiworld.regions.append(self.body_l)
self.multiworld.regions.append(self.body_rt)
self.multiworld.regions.append(self.body_rb)
self.multiworld.regions.append(self.body_b)
self.multiworld.regions.append(self.final_boss_lobby)
self.multiworld.regions.append(self.final_boss_tube)
self.multiworld.regions.append(self.final_boss)
self.multiworld.regions.append(self.final_boss_end)
def add_regions_to_world(self, options: AquariaOptions) -> None:
"""
Add every region to the `world`
"""
self.__add_home_water_regions_to_world()
self.__add_open_water_regions_to_world()
self.__add_mithalas_regions_to_world()
self.__add_forest_regions_to_world()
self.__add_veil_regions_to_world()
self.__add_abyss_regions_to_world()
self.__add_body_regions_to_world()
if self.is_four_gods:
self.multiworld.regions.append(self.four_gods_end)
def __init__(self, multiworld: MultiWorld, player: int, options: AquariaOptions):
"""
Initialisation of the regions
"""
self.multiworld = multiworld
self.player = player
self.is_four_gods = (options.objective.value == Objective.option_killing_the_four_gods or
options.objective.value == Objective.option_gods_and_creator)
self.__create_home_water_area()
self.__create_energy_temple()
self.__create_openwater()
self.__create_mithalas()
self.__create_forest()
self.__create_veil()
self.__create_sun_temple()
self.__create_abyss(not self.is_four_gods)
self.__create_sunken_city(not self.is_four_gods)
self.__create_body(not self.is_four_gods)
if self.is_four_gods:
self.four_gods_end = self.__add_region("Four gods ending", None)