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).
This commit is contained in:
Louis M
2026-02-15 13:20:45 -05:00
committed by GitHub
parent 78e8082a6f
commit 13b6a5f4b2
27 changed files with 1624 additions and 168 deletions

View File

@@ -29,6 +29,7 @@ class ItemGroup(Enum):
UTILITY = 4
SONG = 5
TURTLE = 6
DOOR = 7
class AquariaItem(Item):
@@ -211,6 +212,7 @@ class ItemNames:
TRANSTURTLE_BODY = "Transturtle Final Boss"
TRANSTURTLE_SIMON_SAYS = "Transturtle Simon Says"
TRANSTURTLE_ARNASSI_RUINS = "Transturtle Arnassi Ruins"
DOOR_TO_CATHEDRAL = "Door to the Cathedral opened"
# Events name
BODY_TONGUE_CLEARED = "Body Tongue cleared"
HAS_SUN_CRYSTAL = "Has Sun Crystal"
@@ -240,7 +242,7 @@ item_table = {
ItemNames.BIG_SEED: ItemData(698002, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_big_seed
ItemNames.GLOWING_SEED: ItemData(698003, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_bio_seed
ItemNames.BLACK_PEARL: ItemData(698004, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_blackpearl
ItemNames.BABY_BLASTER: ItemData(698005, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_blaster
ItemNames.BABY_BLASTER: ItemData(698005, 1, ItemType.PROGRESSION, ItemGroup.UTILITY), # collectible_blaster
ItemNames.CRAB_ARMOR: ItemData(698006, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_crab_costume
ItemNames.BABY_DUMBO: ItemData(698007, 1, ItemType.PROGRESSION, ItemGroup.UTILITY), # collectible_dumbo
ItemNames.TOOTH: ItemData(698008, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_energy_boss
@@ -256,8 +258,8 @@ item_table = {
ItemNames.MITHALAS_BANNER: ItemData(698018, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mithalas_banner
ItemNames.MITHALAS_POT: ItemData(698019, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mithalas_pot
ItemNames.MUTANT_COSTUME: ItemData(698020, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_mutant_costume
ItemNames.BABY_NAUTILUS: ItemData(698021, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_nautilus
ItemNames.BABY_PIRANHA: ItemData(698022, 1, ItemType.NORMAL, ItemGroup.UTILITY), # collectible_piranha
ItemNames.BABY_NAUTILUS: ItemData(698021, 1, ItemType.PROGRESSION, ItemGroup.UTILITY), # collectible_nautilus
ItemNames.BABY_PIRANHA: ItemData(698022, 1, ItemType.PROGRESSION, ItemGroup.UTILITY), # collectible_piranha
ItemNames.ARNASSI_ARMOR: ItemData(698023, 1, ItemType.PROGRESSION, ItemGroup.UTILITY), # collectible_seahorse_costume
ItemNames.SEED_BAG: ItemData(698024, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_seed_bag
ItemNames.KING_S_SKULL: ItemData(698025, 1, ItemType.JUNK, ItemGroup.COLLECTIBLE), # collectible_skull
@@ -371,4 +373,20 @@ item_table = {
ItemNames.TRANSTURTLE_BODY: ItemData(698131, 1, ItemType.PROGRESSION, ItemGroup.TURTLE), # transport_finalboss
ItemNames.TRANSTURTLE_SIMON_SAYS: ItemData(698132, 1, ItemType.PROGRESSION, ItemGroup.TURTLE), # transport_forest05
ItemNames.TRANSTURTLE_ARNASSI_RUINS: ItemData(698133, 1, ItemType.PROGRESSION, ItemGroup.TURTLE), # transport_seahorse
ItemNames.DOOR_TO_CATHEDRAL: ItemData(698134, 1, ItemType.PROGRESSION, ItemGroup.DOOR), # door_to_cathedral
}
four_gods_excludes = [ItemNames.ANEMONE, ItemNames.ARNASSI_STATUE, ItemNames.BIG_SEED, ItemNames.GLOWING_SEED,
ItemNames.BLACK_PEARL, ItemNames.TOOTH, ItemNames.ENERGY_STATUE, ItemNames.KROTITE_ARMOR,
ItemNames.GOLDEN_STARFISH, ItemNames.GOLDEN_GEAR, ItemNames.JELLY_BEACON,
ItemNames.JELLY_PLANT, ItemNames.MITHALAS_DOLL, ItemNames.MITHALAN_DRESS,
ItemNames.MITHALAS_BANNER, ItemNames.MITHALAS_POT, ItemNames.MUTANT_COSTUME, ItemNames.SEED_BAG,
ItemNames.KING_S_SKULL, ItemNames.SONG_PLANT_SPORE, ItemNames.STONE_HEAD, ItemNames.SUN_KEY,
ItemNames.GIRL_COSTUME, ItemNames.ODD_CONTAINER, ItemNames.TRIDENT, ItemNames.TURTLE_EGG,
ItemNames.JELLY_EGG, ItemNames.URCHIN_COSTUME, ItemNames.BABY_WALKER,
ItemNames.RAINBOW_MUSHROOM, ItemNames.RAINBOW_MUSHROOM, ItemNames.RAINBOW_MUSHROOM,
ItemNames.LEAF_POULTICE, ItemNames.LEAF_POULTICE, ItemNames.LEAF_POULTICE,
ItemNames.LEECHING_POULTICE, ItemNames.LEECHING_POULTICE, ItemNames.ARCANE_POULTICE,
ItemNames.ROTTEN_MEAT, ItemNames.ROTTEN_MEAT, ItemNames.ROTTEN_MEAT, ItemNames.ROTTEN_MEAT,
ItemNames.SEA_LOAF_X_2, ItemNames.SMALL_EGG]

View File

@@ -233,7 +233,7 @@ class AquariaLocationNames:
SUN_TEMPLE_BULB_AT_THE_TOP_OF_THE_HIGH_DARK_ROOM = "Sun Temple, bulb at the top of the high dark room"
SUN_TEMPLE_GOLDEN_GEAR = "Sun Temple, Golden Gear"
SUN_TEMPLE_FIRST_BULB_OF_THE_TEMPLE = "Sun Temple, first bulb of the temple"
SUN_TEMPLE_BULB_ON_THE_RIGHT_PART = "Sun Temple, bulb on the right part"
SUN_TEMPLE_BULB_ON_THE_RIGHT_PART = "Sun Temple, bulb in the right part"
SUN_TEMPLE_BULB_IN_THE_HIDDEN_ROOM_OF_THE_RIGHT_PART = "Sun Temple, bulb in the hidden room of the right part"
SUN_TEMPLE_SUN_KEY = "Sun Temple, Sun Key"
SUN_TEMPLE_BOSS_PATH_FIRST_PATH_BULB = "Sun Temple boss path, first path bulb"
@@ -306,6 +306,7 @@ class AquariaLocationNames:
BEATING_CRABBIUS_MAXIMUS = "Beating Crabbius Maximus"
BEATING_MANTIS_SHRIMP_PRIME = "Beating Mantis Shrimp Prime"
BEATING_KING_JELLYFISH_GOD_PRIME = "Beating King Jellyfish God Prime"
SITTING_ON_THRONE = "Mithalas City Castle, sitting on the sealed throne"
FIRST_SECRET = "First Secret"
SECOND_SECRET = "Second Secret"
THIRD_SECRET = "Third Secret"
@@ -497,6 +498,7 @@ class AquariaLocations:
locations_mithalas_castle = {
AquariaLocationNames.MITHALAS_CITY_CASTLE_BULB_IN_THE_FLESH_HOLE: 698042,
AquariaLocationNames.MITHALAS_CITY_CASTLE_BLUE_BANNER: 698165,
AquariaLocationNames.SITTING_ON_THRONE: 698218,
}
locations_mithalas_castle_urns = {
@@ -803,6 +805,10 @@ class AquariaLocations:
AquariaLocationNames.FINAL_BOSS_AREA_TRANSTURTLE: 698215,
}
locations_final_boss_tube_transturtle_only = {
AquariaLocationNames.FINAL_BOSS_AREA_TRANSTURTLE: 698215,
}
locations_final_boss = {
AquariaLocationNames.FINAL_BOSS_AREA_BULB_IN_THE_BOSS_THIRD_FORM_ROOM: 698106,
}

View File

@@ -11,9 +11,11 @@ from Options import Toggle, Choice, Range, PerGameCommonOptions, DefaultOnToggle
class IngredientRandomizer(Choice):
"""
Select if the simple ingredients (that do not have a recipe) should be randomized.
If "Common Ingredients" is selected, the randomization will exclude the "Red Bulb", "Special Bulb" and "Rukh Egg".
"""
display_name = "Randomize Ingredients"
rich_text_doc = True
option_off = 0
alias_false = 0
option_common_ingredients = 1
@@ -26,11 +28,17 @@ class IngredientRandomizer(Choice):
class DishRandomizer(Toggle):
"""Randomize the drop of Dishes (Ingredients with recipe)."""
display_name = "Dish Randomizer"
rich_text_doc = True
class TurtleRandomizer(Choice):
"""Randomize the transportation turtle."""
"""
Randomize the transportation turtle.
If the objective is "killing the four gods" or "Gods and Creator", the abyss and body turtle will not be randomized.
"""
display_name = "Turtle Randomizer"
rich_text_doc = True
option_none = 0
alias_off = 0
alias_false = 0
@@ -47,6 +55,7 @@ class EarlyBindSong(Choice):
selected).
"""
display_name = "Early Bind song"
rich_text_doc = True
option_off = 0
alias_false = 0
option_early = 1
@@ -62,6 +71,7 @@ class EarlyEnergyForm(Choice):
selected).
"""
display_name = "Early Energy form"
rich_text_doc = True
option_off = 0
alias_false = 0
option_early = 1
@@ -74,14 +84,19 @@ class EarlyEnergyForm(Choice):
class AquarianTranslation(Toggle):
"""Translate the Aquarian scripture in the game into English."""
display_name = "Translate Aquarian"
rich_text_doc = True
class BigBossesToBeat(Range):
"""
The number of big bosses to beat before having access to the creator (the final boss). The big bosses are
"Fallen God", "Mithalan God", "Drunian God", "Lumerean God" and "The Golem".
The number of big bosses to beat before having access to the creator (the final boss).
The big bosses are "Fallen God", "Mithalan God", "Drunian God", "Lumerean God" and "The Golem".
Has no effect if the objective is "killing the four gods" or "Gods and Creator".
"""
display_name = "Big bosses to beat"
rich_text_doc = True
range_start = 0
range_end = 5
default = 0
@@ -89,12 +104,18 @@ class BigBossesToBeat(Range):
class MiniBossesToBeat(Range):
"""
The number of minibosses to beat before having access to the creator (the final boss). The minibosses are
"Nautilus Prime", "Blaster Peg Prime", "Mergog", "Mithalan priests", "Octopus Prime", "Crabbius Maximus",
"Mantis Shrimp Prime" and "King Jellyfish God Prime".
Note that the Energy Statue and Simon Says are not minibosses.
The number of minibosses to beat before having access to the goal.
The minibosses are "Nautilus Prime", "Blaster Peg Prime", "Mergog", "Mithalan priests", "Octopus Prime",
"Crabbius Maximus", "Mantis Shrimp Prime" and "King Jellyfish God Prime".
Note that the "Energy Statue" and "Simon Says" are not minibosses.
Also note that if the objective is "killing the four enemy gods" or "Gods and creator", it might be needed to go in the abyss and
bubble cave to kill "King Jellyfish God Prime" and "Mantis Shrimp Prime".
"""
display_name = "Minibosses to beat"
rich_text_doc = True
range_start = 0
range_end = 8
default = 0
@@ -102,38 +123,48 @@ class MiniBossesToBeat(Range):
class Objective(Choice):
"""
The game objective can be to kill the creator or to kill the creator after obtaining all three secret memories.
**Kill the Creator:** Get to the final boss (the Creator) and beat all it's forms.
**Obtain secrets and kill the Creator:** like the "Kill the Creator", but need to find all three secret memories
before getting to the Creator.
**Killing the four gods:**, Beat all four enemy gods ("Fallen God", "Mithalan God", "Drunian God", "Lumerean God").
**Gods and Creator:** like "Killing the four gods" but you also have to beat the creator.
"""
display_name = "Objective"
rich_text_doc = True
option_kill_the_creator = 0
option_obtain_secrets_and_kill_the_creator = 1
option_killing_the_four_gods = 2
option_gods_and_creator = 3
default = 0
class SkipFirstVision(Toggle):
"""
The first vision in the game, where Naija transforms into Energy Form and gets flooded by enemies, is quite cool but
can be quite long when you already know what is going on. This option can be used to skip this vision.
Skip the first vision in the game, where Naija transforms into Energy Form and gets flooded by enemies.
"""
display_name = "Skip Naija's first vision"
rich_text_doc = True
class NoProgressionHardOrHiddenLocation(Toggle):
"""
Make sure that there are no progression items at hard-to-reach or hard-to-find locations.
Those locations are very High locations (that need beast form, soup and skill to get),
every location in the bubble cave, locations where need you to cross a false wall without any indication,
the Arnassi race, bosses and minibosses. Useful for those that want a more casual run.
"""
display_name = "No progression in hard or hidden locations"
class LightNeededToGetToDarkPlaces(DefaultOnToggle):
class LightNeededToGetToDarkPlaces(Choice):
"""
Make sure that the sun form or the dumbo pet can be acquired before getting to dark places.
Be aware that navigating in dark places without light is extremely difficult.
You can also force the sun form to be accessible by using the "sun form" option.
"""
display_name = "Light needed to get to dark places"
rich_text_doc = True
option_off = 0
alias_false = 0
option_on = 1
alias_true = 1
option_sun_form = 2
default = 1
class BindSongNeededToGetUnderRockBulb(DefaultOnToggle):
@@ -141,23 +172,83 @@ class BindSongNeededToGetUnderRockBulb(DefaultOnToggle):
Make sure that the bind song can be acquired before having to obtain sing bulbs under rocks.
"""
display_name = "Bind song needed to get sing bulbs under rocks"
rich_text_doc = True
class BlindGoal(Toggle):
"""
Hide the goal's requirements from the help page so that you have to go to the last boss door to know
what is needed to access the boss.
Hide the goal's requirements from the help page so that you don't know what is needed to goal.
Note that when you get to the final boss door (or you beat the last gods when the "Killing the four gods"
is selected) you can then see the requirements in the help page.
"""
display_name = "Hide the goal's requirements"
rich_text_doc = True
class InfiniteHotSoup(DefaultOnToggle):
"""
As soon as a "hot soup" is received, the user will never run out of this dish.
This option is recommended if using Ingredient randomization since "hot soup" ingredients may become hard to get
and the "hot soup" is necessary to get to some locations.
"""
display_name = "Infinite Hot Soup"
rich_text_doc = True
class SaveHealing(DefaultOnToggle):
"""
When you save, Naija is healed back to full health. If disabled, saving won't heal Naija.
Note that Naija can still heal by sleeping in some beds in the game (including in her home).
"""
display_name = "Save heal Naija"
rich_text_doc = True
class OpenBodyTongue(Toggle):
"""
Remove the body tongue making the body accessible without going in the sunken city
"""
display_name = "Open the body tongue"
rich_text_doc = True
class SkipFinalBoss3rdForm(Toggle):
"""
The Final boss third form (the hide and seek form) can be easy and quite long. So, this option can be used
to skip this form.
Note that you will still need to deliver the final blow to the 3rd form in order to activate the 4th form animation.
"""
display_name = "Skip final boss third form"
class MaximumIngredientAmount(Range):
"""
The maximum number of the same ingredients that can be stacked on the ingredient inventory.
"""
display_name = "Maximum ingredient amount"
rich_text_doc = True
range_start = 2
range_end = 20
default = 8
class UnconfineHomeWater(Choice):
"""
Open the way out of the Home Waters area so that Naija can go to open water and beyond without the bind song.
**Via energy door:** Open the energy door between the home waters and the open waters
**Via transturtle:** Remove the rock blocking the home water transturtle.
Note that if you turn this option off, it is recommended to turn on the Early Energy form and Early Bind Song
options.
"""
display_name = "Unconfine Home Waters Area"
rich_text_doc = True
option_off = 0
alias_false = 0
option_via_energy_door = 1
@@ -168,6 +259,134 @@ class UnconfineHomeWater(Choice):
default = 0
class ThroneAsLocation(Toggle):
"""
If enabled, sitting on the Mithalas City Castle throne (with the seal on it) will be a location and opening the
door to the Mithalas Cathedral will be an item.
"""
display_name = "Throne as a location"
rich_text_doc = True
class NoProgressionHardOrHiddenLocation(Toggle):
"""
Make sure that there are no progression items at hard-to-reach or hard-to-find locations.
Those locations are very High locations (that need beast form, soup and skill to get), every location in the
bubble cave, locations where need you to cross a false wall without any indication, the Arnassi race,
bosses and minibosses.
Useful for those that want a more casual run.
"""
display_name = "No progression in hard or hidden locations"
rich_text_doc = True
class NoProgressionSimonSays(Toggle):
"""
Make sure that there are no progression items in the says area.
"""
display_name = "No progression in Simon says area"
rich_text_doc = True
class NoProgressionKelpForest(Toggle):
"""
Make sure that there are no progression items in Kelp Forest (excluding Simon says area).
Can be useful to get smaller runs.
"""
display_name = "No progression in Kelp Forest"
class NoProgressionVeil(Toggle):
"""
Make sure that there are no progression items in the Veil.
Can be useful to get smaller runs.
"""
display_name = "No progression in the Veil"
rich_text_doc = True
class NoProgressionMithalas(Toggle):
"""
Make sure that there are no progression items in the Mithalas (city, castle and cathedral).
Can be useful to get smaller runs.
"""
display_name = "No progression in Mithalas"
rich_text_doc = True
class NoProgressionEnergyTemple(Toggle):
"""
Make sure that there are no progression items in the Energy Temple.
Can be useful to get smaller runs.
"""
display_name = "No progression in the Energy Temple"
rich_text_doc = True
class NoProgressionArnassiRuins(Toggle):
"""
Make sure that there are no progression items in the Arnassi Ruins.
Can be useful to get smaller runs.
Note that if the Transportation turtle are not randomize, this include Simon Says area.
"""
display_name = "No progression in Arnassi Ruins"
rich_text_doc = True
class NoProgressionFrozenVeil(Toggle):
"""
Make sure that there are no progression items in the Frozen Veil (including Ice Cavern and Bubble Cave).
Can be useful to get smaller runs.
"""
display_name = "No progression in the Frozen Veil"
rich_text_doc = True
class NoProgressionAbyss(Toggle):
"""
Make sure that there are no progression items in the Abyss.
Can be useful to get smaller runs.
Has no effect if the objective is "killing the four gods".
"""
display_name = "No progression in the Abyss"
rich_text_doc = True
class NoProgressionSunkenCity(Toggle):
"""
Make sure that there are no progression items in the Sunken City.
Can be useful to get smaller runs.
Has no effect if the objective is "killing the four gods".
"""
display_name = "No progression in the Sunken City"
rich_text_doc = True
class NoProgressionBody(Toggle):
"""
Make sure that there are no progression items in the Body (including the before-boss transturtle room
and the boss location).
Can be useful to get smaller runs.
Has no effect if the objective is "killing the four gods".
"""
display_name = "No progression in the Body"
rich_text_doc = True
@dataclass
class AquariaOptions(PerGameCommonOptions):
"""
@@ -183,9 +402,25 @@ class AquariaOptions(PerGameCommonOptions):
light_needed_to_get_to_dark_places: LightNeededToGetToDarkPlaces
bind_song_needed_to_get_under_rock_bulb: BindSongNeededToGetUnderRockBulb
unconfine_home_water: UnconfineHomeWater
no_progression_hard_or_hidden_locations: NoProgressionHardOrHiddenLocation
ingredient_randomizer: IngredientRandomizer
dish_randomizer: DishRandomizer
aquarian_translation: AquarianTranslation
skip_first_vision: SkipFirstVision
blind_goal: BlindGoal
infinite_hot_soup: InfiniteHotSoup
open_body_tongue: OpenBodyTongue
maximum_ingredient_amount: MaximumIngredientAmount
skip_final_boss_3rd_form: SkipFinalBoss3rdForm
save_healing: SaveHealing
throne_as_location: ThroneAsLocation
no_progression_hard_or_hidden_locations: NoProgressionHardOrHiddenLocation
no_progression_simon_says: NoProgressionSimonSays
no_progression_kelp_forest: NoProgressionKelpForest
no_progression_veil: NoProgressionVeil
no_progression_mithalas: NoProgressionMithalas
no_progression_energy_temple: NoProgressionEnergyTemple
no_progression_arnassi_ruins: NoProgressionArnassiRuins
no_progression_frozen_veil: NoProgressionFrozenVeil
no_progression_abyss: NoProgressionAbyss
no_progression_sunken_city: NoProgressionSunkenCity
no_progression_body: NoProgressionBody

View File

@@ -8,7 +8,7 @@ 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
from .Options import AquariaOptions, UnconfineHomeWater, LightNeededToGetToDarkPlaces, Objective
from worlds.generic.Rules import add_rule, set_rule
@@ -116,14 +116,27 @@ def _has_big_bosses(state: CollectionState, player: int) -> bool:
ItemNames.LUMEREAN_GOD_BEATED, ItemNames.THE_GOLEM_BEATED}, player)
def _has_mini_bosses(state: CollectionState, player: int) -> bool:
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,
@@ -133,6 +146,11 @@ 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
@@ -236,10 +254,11 @@ class AquariaRegions:
body_rt: Region
body_rb: Region
body_b: Region
final_boss_loby: 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
"""
@@ -254,6 +273,11 @@ class AquariaRegions:
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:
"""
@@ -439,65 +463,82 @@ class AquariaRegions:
self.sun_temple_boss = self.__add_region("Sun Temple boss area",
AquariaLocations.locations_sun_temple_boss)
def __create_abyss(self) -> None:
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)
self.abyss_lb = self.__add_region("Abyss left bottom area", AquariaLocations.locations_abyss_lb)
self.abyss_r = self.__add_region("Abyss right area", AquariaLocations.locations_abyss_r)
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)
self.ice_cave = self.__add_region("Ice Cavern", AquariaLocations.locations_ice_cave)
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)
self.bubble_cave_boss = self.__add_region("Bubble Cave boss area", AquariaLocations.locations_bubble_cave_boss)
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)
self.whale = self.__add_region("Inside the whale", AquariaLocations.locations_whale)
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) -> 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)
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)
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)
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)
AquariaLocations.locations_sunken_city_boss
if add_locations else None)
def __create_body(self) -> 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)
AquariaLocations.locations_body_c if add_locations else None)
self.body_l = self.__add_region("The Body left area",
AquariaLocations.locations_body_l)
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)
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)
AquariaLocations.locations_body_rb if add_locations else None)
self.body_b = self.__add_region("The Body bottom area",
AquariaLocations.locations_body_b)
self.final_boss_loby = self.__add_region("The Body, before final boss", None)
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)
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)
AquariaLocations.locations_final_boss if add_locations else None)
self.final_boss_end = self.__add_region("The Body, final boss area", None)
def get_entrance_name(self, from_region: Region, to_region: Region):
@staticmethod
def get_entrance_name(from_region: Region, to_region: Region):
"""
Return the name of an entrance between `from_region` and `to_region`
"""
@@ -510,6 +551,7 @@ class AquariaRegions:
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)
@@ -633,8 +675,8 @@ class AquariaRegions:
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_one_way_regions(self.mithalas_castle, self.cathedral_top_start,
lambda state: _has_bind_song(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,
@@ -708,16 +750,14 @@ class AquariaRegions:
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_bind_song(state, self.player) or
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_one_way_regions(self.sun_temple_l, self.sun_temple_boss_path)
self.__connect_one_way_regions(self.sun_temple_boss_path, self.sun_temple_l)
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)
@@ -800,17 +840,31 @@ class AquariaRegions:
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_loby,
self.__connect_regions(self.body_b, self.final_boss_lobby,
lambda state: _has_dual_form(state, self.player))
self.__connect_regions(self.final_boss_loby, self.final_boss_tube,
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_loby, self.final_boss,
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:
@@ -824,10 +878,10 @@ class AquariaRegions:
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_ABYSS, region, self.abyss_r_transturtle)
self.__connect_transturtle(ItemNames.TRANSTURTLE_BODY, region, self.final_boss_tube)
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"""
@@ -836,12 +890,12 @@ class AquariaRegions:
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.abyss_r_transturtle)
self._connect_transturtle_to_other(self.final_boss_tube)
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) -> None:
def connect_regions(self, options: AquariaOptions) -> None:
"""
Connect every region (entrances and exits)
"""
@@ -853,6 +907,8 @@ class AquariaRegions:
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:
@@ -934,21 +990,25 @@ class AquariaRegions:
AquariaLocationNames.THIRD_SECRET,
ItemNames.THIRD_SECRET_OBTAINED)
def add_event_locations(self) -> None:
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_big_bosses()
self.__add_event_secrets()
self.__add_event_location(self.sunken_city_boss,
AquariaLocationNames.SUNKEN_CITY_CLEARED,
ItemNames.BODY_TONGUE_CLEARED)
self.__add_event_location(self.sun_temple_r,
AquariaLocationNames.SUN_CRYSTAL,
ItemNames.HAS_SUN_CRYSTAL)
self.__add_event_location(self.final_boss_end, AquariaLocationNames.OBJECTIVE_COMPLETE,
ItemNames.VICTORY)
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:
"""
@@ -958,16 +1018,16 @@ class AquariaRegions:
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), combine="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), combine="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) -> None:
def __adjusting_under_rock_location(self, options: AquariaOptions) -> None:
"""
Modify rules implying bind song needed for bulb under rocks
"""
@@ -999,21 +1059,29 @@ class AquariaRegions:
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.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))
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) -> None:
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: _has_light(state, 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: _has_light(state, 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))
@@ -1022,15 +1090,15 @@ class AquariaRegions:
_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: _has_light(state, 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: _has_light(state, 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: _has_light(state, 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: _has_light(state, self.player))
lambda state: light_lambda(state, self.player))
def __adjusting_manual_rules(self) -> None:
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(
@@ -1045,9 +1113,6 @@ class AquariaRegions:
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.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.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),
@@ -1076,19 +1141,21 @@ class AquariaRegions:
), 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.SUN_TEMPLE_BOSS_PATH_FIRST_CLIFF_BULB, self.player),
lambda state: state.has("Sun God beated", self.player))
add_rule(self.multiworld.get_location(AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_SECOND_CLIFF_BULB, self.player),
lambda state: state.has("Sun God beated", 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))
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) -> None:
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,
@@ -1097,8 +1164,6 @@ class AquariaRegions:
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.SUNKEN_CITY_BULB_ON_TOP_OF_THE_BOSS_AREA,
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,
@@ -1109,25 +1174,12 @@ class AquariaRegions:
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.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.FINAL_BOSS_AREA_BULB_IN_THE_BOSS_THIRD_FORM_ROOM,
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.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
self.multiworld.get_location(
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_BULB_CLOSE_TO_THE_SPIRIT_CRYSTALS,
self.player).item_rule = _item_not_advancement
@@ -1135,33 +1187,183 @@ class AquariaRegions:
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.THE_BODY_BOTTOM_AREA_MUTANT_COSTUME,
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()
self.__adjusting_manual_rules(options)
self.__adjusting_soup_rules()
if options.light_needed_to_get_to_dark_places:
self.__adjusting_light_in_dark_place_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()
if options.mini_bosses_to_beat.value > 0:
add_rule(self.multiworld.get_entrance(self.get_entrance_name(self.final_boss_loby, 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_loby, 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_loby, self.final_boss),
self.player), lambda state: _has_secrets(state, self.player))
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),
@@ -1173,7 +1375,7 @@ class AquariaRegions:
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()
self.__no_progression_hard_or_hidden_location(options)
def __add_home_water_regions_to_world(self) -> None:
"""
@@ -1298,12 +1500,12 @@ class AquariaRegions:
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_loby)
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) -> None:
def add_regions_to_world(self, options: AquariaOptions) -> None:
"""
Add every region to the `world`
"""
@@ -1314,13 +1516,17 @@ class AquariaRegions:
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):
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()
@@ -1328,6 +1534,8 @@ class AquariaRegions:
self.__create_forest()
self.__create_veil()
self.__create_sun_temple()
self.__create_abyss()
self.__create_sunken_city()
self.__create_body()
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)

View File

@@ -7,12 +7,14 @@ Description: Main module for Aquaria game multiworld randomizer
from typing import List, Dict, ClassVar, Any
from worlds.AutoWorld import World, WebWorld
from BaseClasses import Tutorial, MultiWorld, ItemClassification
from .Items import item_table, AquariaItem, ItemType, ItemGroup, ItemNames
from .Items import item_table, AquariaItem, ItemType, ItemGroup, ItemNames, four_gods_excludes
from .Locations import location_table, AquariaLocationNames
from .Options import (AquariaOptions, IngredientRandomizer, TurtleRandomizer, EarlyBindSong, EarlyEnergyForm,
UnconfineHomeWater, Objective)
from .Regions import AquariaRegions
CLIENT_MINIMAL_COMPATIBILITY = [1, 4, 1]
class AquariaWeb(WebWorld):
"""
@@ -98,6 +100,7 @@ class AquariaWorld(World):
"Used to manage Regions"
exclude: List[str]
"The items that should not be added to the multiworld item pool"
def __init__(self, multiworld: MultiWorld, player: int):
"""Initialisation of the Aquaria World"""
@@ -111,15 +114,15 @@ class AquariaWorld(World):
Run before any general steps of the MultiWorld other than options. Useful for getting and adjusting option
results and determining layouts for entrance rando etc. start inventory gets pushed after this step.
"""
self.regions = AquariaRegions(self.multiworld, self.player)
self.regions = AquariaRegions(self.multiworld, self.player, self.options)
def create_regions(self) -> None:
"""
Create every Region in `regions`
"""
self.regions.add_regions_to_world()
self.regions.connect_regions()
self.regions.add_event_locations()
self.regions.add_regions_to_world(self.options)
self.regions.connect_regions(self.options)
self.regions.add_event_locations(self.options)
def create_item(self, name: str) -> AquariaItem:
"""
@@ -157,8 +160,17 @@ class AquariaWorld(World):
def create_items(self) -> None:
"""Create every item in the world"""
precollected = [item.name for item in self.multiworld.precollected_items[self.player]]
if (self.options.objective.value == Objective.option_killing_the_four_gods or
self.options.objective.value == Objective.option_gods_and_creator):
self.exclude.extend(four_gods_excludes)
self.__pre_fill_item(ItemNames.TRANSTURTLE_ABYSS, AquariaLocationNames.ABYSS_RIGHT_AREA_TRANSTURTLE,
precollected)
self.__pre_fill_item(ItemNames.TRANSTURTLE_BODY, AquariaLocationNames.FINAL_BOSS_AREA_TRANSTURTLE,
precollected)
if self.options.turtle_randomizer.value != TurtleRandomizer.option_none:
if self.options.turtle_randomizer.value == TurtleRandomizer.option_all_except_final:
if (self.options.turtle_randomizer.value == TurtleRandomizer.option_all_except_final and
self.options.objective.value != Objective.option_killing_the_four_gods and
self.options.objective.value != Objective.option_gods_and_creator):
self.__pre_fill_item(ItemNames.TRANSTURTLE_BODY, AquariaLocationNames.FINAL_BOSS_AREA_TRANSTURTLE,
precollected)
else:
@@ -167,25 +179,29 @@ class AquariaWorld(World):
self.__pre_fill_item(ItemNames.TRANSTURTLE_VEIL_TOP_RIGHT,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_TRANSTURTLE, precollected)
self.__pre_fill_item(ItemNames.TRANSTURTLE_OPEN_WATERS,
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_TRANSTURTLE,
precollected)
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_TRANSTURTLE, precollected)
self.__pre_fill_item(ItemNames.TRANSTURTLE_KELP_FOREST,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_TRANSTURTLE,
precollected)
self.__pre_fill_item(ItemNames.TRANSTURTLE_HOME_WATERS, AquariaLocationNames.HOME_WATERS_TRANSTURTLE,
precollected)
self.__pre_fill_item(ItemNames.TRANSTURTLE_ABYSS, AquariaLocationNames.ABYSS_RIGHT_AREA_TRANSTURTLE,
precollected)
self.__pre_fill_item(ItemNames.TRANSTURTLE_BODY, AquariaLocationNames.FINAL_BOSS_AREA_TRANSTURTLE,
precollected)
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_TRANSTURTLE, precollected)
self.__pre_fill_item(ItemNames.TRANSTURTLE_HOME_WATERS, AquariaLocationNames.HOME_WATERS_TRANSTURTLE, precollected)
if (self.options.objective.value != Objective.option_killing_the_four_gods and
self.options.objective.value != Objective.option_gods_and_creator):
self.__pre_fill_item(ItemNames.TRANSTURTLE_ABYSS, AquariaLocationNames.ABYSS_RIGHT_AREA_TRANSTURTLE,
precollected)
self.__pre_fill_item(ItemNames.TRANSTURTLE_BODY, AquariaLocationNames.FINAL_BOSS_AREA_TRANSTURTLE,
precollected)
# The last two are inverted because in the original game, they are special turtle that communicate directly
self.__pre_fill_item(ItemNames.TRANSTURTLE_SIMON_SAYS, AquariaLocationNames.ARNASSI_RUINS_TRANSTURTLE,
precollected, ItemClassification.progression)
self.__pre_fill_item(ItemNames.TRANSTURTLE_ARNASSI_RUINS, AquariaLocationNames.SIMON_SAYS_AREA_TRANSTURTLE,
precollected)
if not self.options.throne_as_location:
self.__pre_fill_item(ItemNames.DOOR_TO_CATHEDRAL, AquariaLocationNames.SITTING_ON_THRONE,
precollected, ItemClassification.progression)
for name, data in item_table.items():
if name not in self.exclude:
for i in range(data.count):
for i in range(data.count):
if name in self.exclude:
self.exclude.remove(name)
else:
item = self.create_item(name)
self.multiworld.itempool.append(item)
@@ -227,22 +243,41 @@ class AquariaWorld(World):
self.ingredients_substitution.extend(dishes_substitution)
def fill_slot_data(self) -> Dict[str, Any]:
"""
Send some useful information to the client.
"""
return {"ingredientReplacement": self.ingredients_substitution,
"aquarian_translate": bool(self.options.aquarian_translation.value),
"blind_goal": bool(self.options.blind_goal.value),
"secret_needed":
self.options.objective.value == Objective.option_obtain_secrets_and_kill_the_creator,
"goal": self.options.objective.value,
"minibosses_to_kill": self.options.mini_bosses_to_beat.value,
"bigbosses_to_kill": self.options.big_bosses_to_beat.value,
"skip_first_vision": bool(self.options.skip_first_vision.value),
"skip_final_boss_3rd_form": bool(self.options.skip_final_boss_3rd_form.value),
"infinite_hot_soup": bool(self.options.infinite_hot_soup.value),
"open_body_tongue": bool(self.options.open_body_tongue.value),
"unconfine_home_water_energy_door":
self.options.unconfine_home_water.value == UnconfineHomeWater.option_via_energy_door
or self.options.unconfine_home_water.value == UnconfineHomeWater.option_via_both,
"unconfine_home_water_transturtle":
self.options.unconfine_home_water.value == UnconfineHomeWater.option_via_transturtle
or self.options.unconfine_home_water.value == UnconfineHomeWater.option_via_both,
"maximum_ingredient_amount": self.options.maximum_ingredient_amount.value,
"bind_song_needed_to_get_under_rock_bulb": bool(self.options.bind_song_needed_to_get_under_rock_bulb),
"no_progression_hard_or_hidden_locations": bool(self.options.no_progression_hard_or_hidden_locations),
"light_needed_to_get_to_dark_places": bool(self.options.light_needed_to_get_to_dark_places),
"turtle_randomizer": self.options.turtle_randomizer.value
"turtle_randomizer": self.options.turtle_randomizer.value,
"no_progression_simon_says": bool(self.options.no_progression_simon_says),
"no_progression_kelp_forest": bool(self.options.no_progression_kelp_forest),
"no_progression_veil": bool(self.options.no_progression_veil),
"no_progression_mithalas": bool(self.options.no_progression_mithalas),
"no_progression_energy_temple": bool(self.options.no_progression_energy_temple),
"no_progression_arnassi_ruins": bool(self.options.no_progression_arnassi_ruins),
"no_progression_frozen_veil": bool(self.options.no_progression_frozen_veil),
"no_progression_abyss": bool(self.options.no_progression_abyss),
"no_progression_sunken_city": bool(self.options.no_progression_sunken_city),
"no_progression_body": bool(self.options.no_progression_body),
"save_healing": bool(self.options.save_healing),
"throne_as_location": bool(self.options.throne_as_location),
"required_client_version": CLIENT_MINIMAL_COMPATIBILITY,
}

View File

@@ -0,0 +1,185 @@
"""
Author: Louis M
Date: Thu, 18 Apr 2024 18:45:56 +0000
Description: Unit test used to test accessibility of locations with the goal four gods
"""
from . import AquariaTestBase
from ..Items import ItemNames
from ..Locations import AquariaLocationNames
from ..Options import UnconfineHomeWater, Objective, BindSongNeededToGetUnderRockBulb
class FourGodsAccessTest(AquariaTestBase):
"""Unit test used to test accessibility of locations with the goal four gods"""
options = {
"objective": Objective.option_killing_the_four_gods,
"bind_song_needed_to_get_under_rock_bulb": BindSongNeededToGetUnderRockBulb.option_true
}
def test_locations(self) -> None:
"""Test locations with the goal four gods"""
locations = [
AquariaLocationNames.VERSE_CAVE_RIGHT_AREA_BIG_SEED,
AquariaLocationNames.VERSE_CAVE_LEFT_AREA_BULB_UNDER_THE_ROCK_AT_THE_END_OF_THE_PATH,
AquariaLocationNames.HOME_WATERS_BULB_UNDER_THE_ROCK_IN_THE_LEFT_PATH_FROM_THE_VERSE_CAVE,
AquariaLocationNames.HOME_WATERS_BULB_IN_THE_PATH_BELOW_NAUTILUS_PRIME,
AquariaLocationNames.HOME_WATERS_BULB_IN_THE_BOTTOM_LEFT_ROOM,
AquariaLocationNames.HOME_WATERS_NAUTILUS_EGG,
AquariaLocationNames.HOME_WATERS_TRANSTURTLE,
AquariaLocationNames.NAIJA_S_HOME_BULB_AFTER_THE_ENERGY_DOOR,
AquariaLocationNames.NAIJA_S_HOME_BULB_UNDER_THE_ROCK_AT_THE_RIGHT_OF_THE_MAIN_PATH,
AquariaLocationNames.SONG_CAVE_BULB_UNDER_THE_ROCK_IN_THE_PATH_TO_THE_SINGING_STATUES,
AquariaLocationNames.SONG_CAVE_BULB_UNDER_THE_ROCK_CLOSE_TO_THE_SONG_DOOR,
AquariaLocationNames.SONG_CAVE_VERSE_EGG,
AquariaLocationNames.SONG_CAVE_ANEMONE_SEED,
AquariaLocationNames.ENERGY_TEMPLE_FIRST_AREA_BEATING_THE_ENERGY_STATUE,
AquariaLocationNames.ENERGY_TEMPLE_FIRST_AREA_BULB_IN_THE_BOTTOM_ROOM_BLOCKED_BY_A_ROCK,
AquariaLocationNames.ENERGY_TEMPLE_ENERGY_IDOL,
AquariaLocationNames.ENERGY_TEMPLE_SECOND_AREA_BULB_UNDER_THE_ROCK,
AquariaLocationNames.ENERGY_TEMPLE_BOTTOM_ENTRANCE_KROTITE_ARMOR,
AquariaLocationNames.ENERGY_TEMPLE_THIRD_AREA_BULB_IN_THE_BOTTOM_PATH,
AquariaLocationNames.ENERGY_TEMPLE_BOSS_AREA_FALLEN_GOD_TOOTH,
AquariaLocationNames.ENERGY_TEMPLE_BLASTER_ROOM_BLASTER_EGG,
AquariaLocationNames.OPEN_WATERS_TOP_LEFT_AREA_BULB_UNDER_THE_ROCK_IN_THE_RIGHT_PATH,
AquariaLocationNames.OPEN_WATERS_TOP_LEFT_AREA_BULB_UNDER_THE_ROCK_IN_THE_LEFT_PATH,
AquariaLocationNames.OPEN_WATERS_TOP_LEFT_AREA_BULB_TO_THE_RIGHT_OF_THE_SAVE_CRYSTAL,
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_BULB_IN_THE_SMALL_PATH_BEFORE_MITHALAS,
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_BULB_IN_THE_PATH_FROM_THE_LEFT_ENTRANCE,
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_BULB_IN_THE_CLEARING_CLOSE_TO_THE_BOTTOM_EXIT,
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_BULB_IN_THE_BIG_CLEARING_CLOSE_TO_THE_SAVE_CRYSTAL,
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_BULB_IN_THE_BIG_CLEARING_TO_THE_TOP_EXIT,
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_BULB_IN_THE_TURTLE_ROOM,
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_TRANSTURTLE,
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_FIRST_URN_IN_THE_MITHALAS_EXIT,
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_SECOND_URN_IN_THE_MITHALAS_EXIT,
AquariaLocationNames.OPEN_WATERS_TOP_RIGHT_AREA_THIRD_URN_IN_THE_MITHALAS_EXIT,
AquariaLocationNames.OPEN_WATERS_BOTTOM_LEFT_AREA_BULB_BEHIND_THE_CHOMPER_FISH,
AquariaLocationNames.OPEN_WATERS_BOTTOM_LEFT_AREA_BULB_INSIDE_THE_LOWEST_FISH_PASS,
AquariaLocationNames.OPEN_WATERS_SKELETON_PATH_BULB_CLOSE_TO_THE_RIGHT_EXIT,
AquariaLocationNames.OPEN_WATERS_SKELETON_PATH_BULB_BEHIND_THE_CHOMPER_FISH,
AquariaLocationNames.OPEN_WATERS_SKELETON_PATH_KING_SKULL,
AquariaLocationNames.ARNASSI_RUINS_BULB_IN_THE_RIGHT_PART,
AquariaLocationNames.ARNASSI_RUINS_BULB_IN_THE_LEFT_PART,
AquariaLocationNames.ARNASSI_RUINS_BULB_IN_THE_CENTER_PART,
AquariaLocationNames.ARNASSI_RUINS_SONG_PLANT_SPORE,
AquariaLocationNames.ARNASSI_RUINS_ARNASSI_ARMOR,
AquariaLocationNames.ARNASSI_RUINS_ARNASSI_STATUE,
AquariaLocationNames.ARNASSI_RUINS_TRANSTURTLE,
AquariaLocationNames.ARNASSI_RUINS_CRAB_ARMOR,
AquariaLocationNames.SIMON_SAYS_AREA_BEATING_SIMON_SAYS,
AquariaLocationNames.SIMON_SAYS_AREA_TRANSTURTLE,
AquariaLocationNames.MITHALAS_CITY_FIRST_BULB_IN_THE_LEFT_CITY_PART,
AquariaLocationNames.MITHALAS_CITY_SECOND_BULB_IN_THE_LEFT_CITY_PART,
AquariaLocationNames.MITHALAS_CITY_BULB_IN_THE_RIGHT_PART,
AquariaLocationNames.MITHALAS_CITY_BULB_AT_THE_TOP_OF_THE_CITY,
AquariaLocationNames.MITHALAS_CITY_FIRST_BULB_IN_A_BROKEN_HOME,
AquariaLocationNames.MITHALAS_CITY_SECOND_BULB_IN_A_BROKEN_HOME,
AquariaLocationNames.MITHALAS_CITY_BULB_IN_THE_BOTTOM_LEFT_PART,
AquariaLocationNames.MITHALAS_CITY_FIRST_BULB_IN_ONE_OF_THE_HOMES,
AquariaLocationNames.MITHALAS_CITY_SECOND_BULB_IN_ONE_OF_THE_HOMES,
AquariaLocationNames.MITHALAS_CITY_FIRST_URN_IN_ONE_OF_THE_HOMES,
AquariaLocationNames.MITHALAS_CITY_SECOND_URN_IN_ONE_OF_THE_HOMES,
AquariaLocationNames.MITHALAS_CITY_FIRST_URN_IN_THE_CITY_RESERVE,
AquariaLocationNames.MITHALAS_CITY_SECOND_URN_IN_THE_CITY_RESERVE,
AquariaLocationNames.MITHALAS_CITY_THIRD_URN_IN_THE_CITY_RESERVE,
AquariaLocationNames.MITHALAS_CITY_FIRST_BULB_AT_THE_END_OF_THE_TOP_PATH,
AquariaLocationNames.MITHALAS_CITY_SECOND_BULB_AT_THE_END_OF_THE_TOP_PATH,
AquariaLocationNames.MITHALAS_CITY_BULB_IN_THE_TOP_PATH,
AquariaLocationNames.MITHALAS_CITY_MITHALAS_POT,
AquariaLocationNames.MITHALAS_CITY_URN_IN_THE_CASTLE_FLOWER_TUBE_ENTRANCE,
AquariaLocationNames.MITHALAS_CITY_DOLL,
AquariaLocationNames.MITHALAS_CITY_URN_INSIDE_A_HOME_FISH_PASS,
AquariaLocationNames.MITHALAS_CITY_CASTLE_BULB_IN_THE_FLESH_HOLE,
AquariaLocationNames.MITHALAS_CITY_CASTLE_BLUE_BANNER,
AquariaLocationNames.MITHALAS_CITY_CASTLE_URN_IN_THE_BEDROOM,
AquariaLocationNames.MITHALAS_CITY_CASTLE_FIRST_URN_OF_THE_SINGLE_LAMP_PATH,
AquariaLocationNames.MITHALAS_CITY_CASTLE_SECOND_URN_OF_THE_SINGLE_LAMP_PATH,
AquariaLocationNames.MITHALAS_CITY_CASTLE_URN_IN_THE_BOTTOM_ROOM,
AquariaLocationNames.MITHALAS_CITY_CASTLE_FIRST_URN_ON_THE_ENTRANCE_PATH,
AquariaLocationNames.MITHALAS_CITY_CASTLE_SECOND_URN_ON_THE_ENTRANCE_PATH,
AquariaLocationNames.MITHALAS_CITY_CASTLE_BEATING_THE_PRIESTS,
AquariaLocationNames.MITHALAS_CITY_CASTLE_TRIDENT_HEAD,
AquariaLocationNames.MITHALAS_CATHEDRAL_BULB_IN_THE_FLESH_ROOM_WITH_FLEAS,
AquariaLocationNames.MITHALAS_CATHEDRAL_MITHALAN_DRESS,
AquariaLocationNames.MITHALAS_CATHEDRAL_FIRST_URN_IN_THE_TOP_RIGHT_ROOM,
AquariaLocationNames.MITHALAS_CATHEDRAL_SECOND_URN_IN_THE_TOP_RIGHT_ROOM,
AquariaLocationNames.MITHALAS_CATHEDRAL_THIRD_URN_IN_THE_TOP_RIGHT_ROOM,
AquariaLocationNames.MITHALAS_CATHEDRAL_URN_BEHIND_THE_FLESH_VEIN,
AquariaLocationNames.MITHALAS_CATHEDRAL_URN_IN_THE_TOP_LEFT_EYES_BOSS_ROOM,
AquariaLocationNames.MITHALAS_CATHEDRAL_FIRST_URN_IN_THE_PATH_BEHIND_THE_FLESH_VEIN,
AquariaLocationNames.MITHALAS_CATHEDRAL_SECOND_URN_IN_THE_PATH_BEHIND_THE_FLESH_VEIN,
AquariaLocationNames.MITHALAS_CATHEDRAL_THIRD_URN_IN_THE_PATH_BEHIND_THE_FLESH_VEIN,
AquariaLocationNames.MITHALAS_CATHEDRAL_FOURTH_URN_IN_THE_TOP_RIGHT_ROOM,
AquariaLocationNames.MITHALAS_CATHEDRAL_URN_BELOW_THE_LEFT_ENTRANCE,
AquariaLocationNames.MITHALAS_CATHEDRAL_FIRST_URN_IN_THE_BOTTOM_RIGHT_PATH,
AquariaLocationNames.MITHALAS_CATHEDRAL_SECOND_URN_IN_THE_BOTTOM_RIGHT_PATH,
AquariaLocationNames.CATHEDRAL_UNDERGROUND_BULB_IN_THE_CENTER_PART,
AquariaLocationNames.CATHEDRAL_UNDERGROUND_FIRST_BULB_IN_THE_TOP_LEFT_PART,
AquariaLocationNames.CATHEDRAL_UNDERGROUND_SECOND_BULB_IN_THE_TOP_LEFT_PART,
AquariaLocationNames.CATHEDRAL_UNDERGROUND_THIRD_BULB_IN_THE_TOP_LEFT_PART,
AquariaLocationNames.CATHEDRAL_UNDERGROUND_BULB_CLOSE_TO_THE_SAVE_CRYSTAL,
AquariaLocationNames.CATHEDRAL_UNDERGROUND_BULB_IN_THE_BOTTOM_RIGHT_PATH,
AquariaLocationNames.MITHALAS_BOSS_AREA_BEATING_MITHALAN_GOD,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_BULB_IN_THE_BOTTOM_LEFT_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_BULB_IN_THE_PATH_DOWN_FROM_THE_TOP_LEFT_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_BULB_IN_THE_TOP_LEFT_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_JELLY_EGG,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_BULB_CLOSE_TO_THE_VERSE_EGG,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_VERSE_EGG,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_UNDER_THE_ROCK_IN_THE_RIGHT_PATH,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_AT_THE_LEFT_OF_THE_CENTER_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_IN_THE_LEFT_PATH_S_BIG_ROOM,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_IN_THE_LEFT_PATH_S_SMALL_ROOM,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_AT_THE_TOP_OF_THE_CENTER_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BLACK_PEARL,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_IN_THE_TOP_FISH_PASS,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_TRANSTURTLE,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_BULB_CLOSE_TO_THE_SPIRIT_CRYSTALS,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_WALKER_BABY,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_FISH_CAVE_PUZZLE,
AquariaLocationNames.KELP_FOREST_BOTTOM_RIGHT_AREA_ODD_CONTAINER,
AquariaLocationNames.KELP_FOREST_BOSS_AREA_BEATING_DRUNIAN_GOD,
AquariaLocationNames.KELP_FOREST_BOSS_ROOM_BULB_AT_THE_BOTTOM_OF_THE_AREA,
AquariaLocationNames.KELP_FOREST_SPRITE_CAVE_BULB_INSIDE_THE_FISH_PASS,
AquariaLocationNames.KELP_FOREST_SPRITE_CAVE_BULB_IN_THE_SECOND_ROOM,
AquariaLocationNames.KELP_FOREST_SPRITE_CAVE_SEED_BAG,
AquariaLocationNames.MERMOG_CAVE_BULB_IN_THE_LEFT_PART_OF_THE_CAVE,
AquariaLocationNames.MERMOG_CAVE_PIRANHA_EGG,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_IN_LI_S_CAVE,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_BULB_UNDER_THE_ROCK_IN_THE_TOP_RIGHT_PATH,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_BULB_HIDDEN_BEHIND_THE_BLOCKING_ROCK,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_TRANSTURTLE,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_BULB_INSIDE_THE_FISH_PASS,
AquariaLocationNames.TURTLE_CAVE_TURTLE_EGG,
AquariaLocationNames.TURTLE_CAVE_BULB_IN_BUBBLE_CLIFF,
AquariaLocationNames.TURTLE_CAVE_URCHIN_COSTUME,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_BULB_IN_THE_MIDDLE_OF_THE_WALL_JUMP_CLIFF,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_GOLDEN_STARFISH,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_BULB_AT_THE_TOP_OF_THE_WATERFALL,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_TRANSTURTLE,
AquariaLocationNames.THE_VEIL_BOTTOM_AREA_BULB_IN_THE_LEFT_PATH,
AquariaLocationNames.THE_VEIL_BOTTOM_AREA_BULB_IN_THE_SPIRIT_PATH,
AquariaLocationNames.THE_VEIL_BOTTOM_AREA_VERSE_EGG,
AquariaLocationNames.THE_VEIL_BOTTOM_AREA_STONE_HEAD,
AquariaLocationNames.OCTOPUS_CAVE_DUMBO_EGG,
AquariaLocationNames.OCTOPUS_CAVE_BULB_IN_THE_PATH_BELOW_THE_OCTOPUS_CAVE_PATH,
AquariaLocationNames.SUN_TEMPLE_BULB_IN_THE_TOP_LEFT_PART,
AquariaLocationNames.SUN_TEMPLE_BULB_IN_THE_TOP_RIGHT_PART,
AquariaLocationNames.SUN_TEMPLE_BULB_AT_THE_TOP_OF_THE_HIGH_DARK_ROOM,
AquariaLocationNames.SUN_TEMPLE_GOLDEN_GEAR,
AquariaLocationNames.SUN_TEMPLE_FIRST_BULB_OF_THE_TEMPLE,
AquariaLocationNames.SUN_TEMPLE_BULB_ON_THE_RIGHT_PART,
AquariaLocationNames.SUN_TEMPLE_BULB_IN_THE_HIDDEN_ROOM_OF_THE_RIGHT_PART,
AquariaLocationNames.SUN_TEMPLE_SUN_KEY,
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_FIRST_PATH_BULB,
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_SECOND_PATH_BULB,
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_FIRST_CLIFF_BULB,
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_SECOND_CLIFF_BULB,
AquariaLocationNames.SUN_TEMPLE_BOSS_AREA_BEATING_LUMEREAN_GOD,
]
items = [[ItemNames.ENERGY_FORM, ItemNames.SUN_FORM, ItemNames.BEAST_FORM, ItemNames.SPIRIT_FORM,
ItemNames.FISH_FORM, ItemNames.HOT_SOUP, ItemNames.BIND_SONG, ItemNames.NATURE_FORM,
ItemNames.DUAL_FORM]]
self.assertAccessDependency(locations, items, True)

View File

@@ -0,0 +1,35 @@
"""
Author: Louis M
Date: Thu, 18 Apr 2024 18:45:56 +0000
Description: Unit test used to test accessibility of locations with and without the beast form or hot soup
"""
from . import AquariaTestBase
from ..Locations import AquariaLocationNames
from ..Items import ItemNames
class BeastOrSoupAccessTest(AquariaTestBase):
"""Unit test used to test accessibility of locations with and without the beast form or hot soup"""
def test_beast_or_soup_location(self) -> None:
"""Test locations that require beast form or hot soup"""
locations = [
AquariaLocationNames.MERMOG_CAVE_PIRANHA_EGG,
AquariaLocationNames.MITHALAS_CATHEDRAL_MITHALAN_DRESS,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_JELLY_EGG,
AquariaLocationNames.TURTLE_CAVE_URCHIN_COSTUME,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_BULB_AT_THE_TOP_OF_THE_WATERFALL,
AquariaLocationNames.SUNKEN_CITY_BULB_ON_TOP_OF_THE_BOSS_AREA,
AquariaLocationNames.OCTOPUS_CAVE_DUMBO_EGG,
AquariaLocationNames.BUBBLE_CAVE_BULB_IN_THE_LEFT_CAVE_WALL,
AquariaLocationNames.BUBBLE_CAVE_BULB_IN_THE_RIGHT_CAVE_WALL_BEHIND_THE_ICE_CRYSTAL,
AquariaLocationNames.BUBBLE_CAVE_VERSE_EGG,
AquariaLocationNames.BEATING_MANTIS_SHRIMP_PRIME,
AquariaLocationNames.BEATING_THE_GOLEM,
AquariaLocationNames.BEATING_MERGOG,
AquariaLocationNames.BEATING_OCTOPUS_PRIME,
AquariaLocationNames.SUNKEN_CITY_CLEARED
]
items = [[ItemNames.BEAST_FORM, ItemNames.HOT_SOUP, ItemNames.HOT_SOUP_X_2]]
self.assertAccessDependency(locations, items)

View File

@@ -35,6 +35,7 @@ class BindSongAccessTest(AquariaTestBase):
AquariaLocationNames.ENERGY_TEMPLE_THIRD_AREA_BULB_IN_THE_BOTTOM_PATH,
AquariaLocationNames.ENERGY_TEMPLE_BOSS_AREA_FALLEN_GOD_TOOTH,
AquariaLocationNames.ENERGY_TEMPLE_BLASTER_ROOM_BLASTER_EGG,
AquariaLocationNames.SITTING_ON_THRONE,
*after_home_water_locations
]
items = [[ItemNames.BIND_SONG]]

View File

@@ -38,6 +38,7 @@ class BindSongOptionAccessTest(AquariaTestBase):
AquariaLocationNames.ENERGY_TEMPLE_THIRD_AREA_BULB_IN_THE_BOTTOM_PATH,
AquariaLocationNames.ENERGY_TEMPLE_BOSS_AREA_FALLEN_GOD_TOOTH,
AquariaLocationNames.ENERGY_TEMPLE_BLASTER_ROOM_BLASTER_EGG,
AquariaLocationNames.SITTING_ON_THRONE,
*after_home_water_locations
]
items = [[ItemNames.BIND_SONG]]

View File

@@ -0,0 +1,44 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that no progression items can be put in Arnassi Ruins when option enabled
"""
from . import AquariaTestBase
from BaseClasses import ItemClassification
from ..Locations import AquariaLocationNames
class NoProgressionArnassiRuinsTest(AquariaTestBase):
"""Unit test used to test that no progression items can be put in Arnassi Ruins when option enabled"""
options = {
"no_progression_arnassi_ruins": True
}
unfillable_locations = [
AquariaLocationNames.ARNASSI_RUINS_BULB_IN_THE_RIGHT_PART,
AquariaLocationNames.ARNASSI_RUINS_BULB_IN_THE_LEFT_PART,
AquariaLocationNames.ARNASSI_RUINS_BULB_IN_THE_CENTER_PART,
AquariaLocationNames.ARNASSI_RUINS_SONG_PLANT_SPORE,
AquariaLocationNames.ARNASSI_RUINS_ARNASSI_ARMOR,
AquariaLocationNames.ARNASSI_RUINS_ARNASSI_STATUE,
AquariaLocationNames.ARNASSI_RUINS_TRANSTURTLE,
AquariaLocationNames.ARNASSI_RUINS_CRAB_ARMOR,
]
def test_no_progression_arnassi_ruins(self) -> None:
"""
Unit test used to test that no progression items can be put in Arnassi Ruins when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
if item.classification == ItemClassification.progression:
self.assertFalse(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" can be filled with \"" + item_name + "\"")
else:
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -0,0 +1,44 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that no progression items can be put in Energy Temple when option enabled
"""
from . import AquariaTestBase
from BaseClasses import ItemClassification
from ..Locations import AquariaLocationNames
class NoProgressionEnergyTempleTest(AquariaTestBase):
"""Unit test used to test that no progression items can be put in Energy Temple when option enabled"""
options = {
"no_progression_energy_temple": True
}
unfillable_locations = [
AquariaLocationNames.ENERGY_TEMPLE_FIRST_AREA_BEATING_THE_ENERGY_STATUE,
AquariaLocationNames.ENERGY_TEMPLE_FIRST_AREA_BULB_IN_THE_BOTTOM_ROOM_BLOCKED_BY_A_ROCK,
AquariaLocationNames.ENERGY_TEMPLE_ENERGY_IDOL,
AquariaLocationNames.ENERGY_TEMPLE_SECOND_AREA_BULB_UNDER_THE_ROCK,
AquariaLocationNames.ENERGY_TEMPLE_BOTTOM_ENTRANCE_KROTITE_ARMOR,
AquariaLocationNames.ENERGY_TEMPLE_THIRD_AREA_BULB_IN_THE_BOTTOM_PATH,
AquariaLocationNames.ENERGY_TEMPLE_BOSS_AREA_FALLEN_GOD_TOOTH,
AquariaLocationNames.ENERGY_TEMPLE_BLASTER_ROOM_BLASTER_EGG,
]
def test_no_progression_energy_temple(self) -> None:
"""
Unit test used to test that no progression items can be put in Energy Temple when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
if item.classification == ItemClassification.progression:
self.assertFalse(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" can be filled with \"" + item_name + "\"")
else:
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -0,0 +1,44 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that no progression items can be put in Frozen Veil when option enabled
"""
from . import AquariaTestBase
from BaseClasses import ItemClassification
from ..Locations import AquariaLocationNames
class NoProgressionFrozenVeilTest(AquariaTestBase):
"""Unit test used to test that no progression items can be put in Frozen Veil when option enabled"""
options = {
"no_progression_frozen_veil": True
}
unfillable_locations = [
AquariaLocationNames.ICE_CAVERN_BULB_IN_THE_ROOM_TO_THE_RIGHT,
AquariaLocationNames.ICE_CAVERN_FIRST_BULB_IN_THE_TOP_EXIT_ROOM,
AquariaLocationNames.ICE_CAVERN_SECOND_BULB_IN_THE_TOP_EXIT_ROOM,
AquariaLocationNames.ICE_CAVERN_THIRD_BULB_IN_THE_TOP_EXIT_ROOM,
AquariaLocationNames.ICE_CAVERN_BULB_IN_THE_LEFT_ROOM,
AquariaLocationNames.BUBBLE_CAVE_BULB_IN_THE_LEFT_CAVE_WALL,
AquariaLocationNames.BUBBLE_CAVE_BULB_IN_THE_RIGHT_CAVE_WALL_BEHIND_THE_ICE_CRYSTAL,
AquariaLocationNames.BUBBLE_CAVE_VERSE_EGG,
]
def test_no_progression_frozen_veil(self) -> None:
"""
Unit test used to test that no progression items can be put in Frozen Veil when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
if item.classification == ItemClassification.progression:
self.assertFalse(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" can be filled with \"" + item_name + "\"")
else:
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -9,7 +9,7 @@ from BaseClasses import ItemClassification
from ..Locations import AquariaLocationNames
class UNoProgressionHardHiddenTest(AquariaTestBase):
class NoProgressionHardHiddenTest(AquariaTestBase):
"""Unit test used to test that no progression items can be put in hard or hidden locations when option enabled"""
options = {
"no_progression_hard_or_hidden_locations": True
@@ -43,7 +43,7 @@ class UNoProgressionHardHiddenTest(AquariaTestBase):
AquariaLocationNames.ARNASSI_RUINS_ARNASSI_ARMOR,
]
def test_unconfine_home_water_both_location_fillable(self) -> None:
def test_no_progression_hard_or_hidden(self) -> None:
"""
Unit test used to test that no progression items can be put in hard or hidden locations when option enabled
"""

View File

@@ -0,0 +1,61 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that no progression items can be put in Kelp Forest when option enabled
"""
from . import AquariaTestBase
from BaseClasses import ItemClassification
from ..Locations import AquariaLocationNames
class NoProgressionKelpForestTest(AquariaTestBase):
"""Unit test used to test that no progression items can be put in Kelp Forest when option enabled"""
options = {
"no_progression_kelp_forest": True
}
unfillable_locations = [
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_BULB_IN_THE_BOTTOM_LEFT_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_BULB_IN_THE_PATH_DOWN_FROM_THE_TOP_LEFT_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_BULB_IN_THE_TOP_LEFT_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_JELLY_EGG,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_BULB_CLOSE_TO_THE_VERSE_EGG,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_VERSE_EGG,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_UNDER_THE_ROCK_IN_THE_RIGHT_PATH,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_AT_THE_LEFT_OF_THE_CENTER_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_IN_THE_LEFT_PATH_S_BIG_ROOM,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_IN_THE_LEFT_PATH_S_SMALL_ROOM,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_AT_THE_TOP_OF_THE_CENTER_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BLACK_PEARL,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_IN_THE_TOP_FISH_PASS,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_BULB_CLOSE_TO_THE_SPIRIT_CRYSTALS,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_WALKER_BABY,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_TRANSTURTLE,
AquariaLocationNames.KELP_FOREST_BOTTOM_RIGHT_AREA_ODD_CONTAINER,
AquariaLocationNames.KELP_FOREST_BOSS_AREA_BEATING_DRUNIAN_GOD,
AquariaLocationNames.KELP_FOREST_BOSS_ROOM_BULB_AT_THE_BOTTOM_OF_THE_AREA,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_FISH_CAVE_PUZZLE,
AquariaLocationNames.KELP_FOREST_SPRITE_CAVE_BULB_INSIDE_THE_FISH_PASS,
AquariaLocationNames.KELP_FOREST_SPRITE_CAVE_BULB_IN_THE_SECOND_ROOM,
AquariaLocationNames.KELP_FOREST_SPRITE_CAVE_SEED_BAG,
AquariaLocationNames.MERMOG_CAVE_BULB_IN_THE_LEFT_PART_OF_THE_CAVE,
AquariaLocationNames.MERMOG_CAVE_PIRANHA_EGG,
]
def test_no_progression_kelp_forest(self) -> None:
"""
Unit test used to test that no progression items can be put in Kelp Forest when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
if item.classification == ItemClassification.progression:
self.assertFalse(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" can be filled with \"" + item_name + "\"")
else:
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -0,0 +1,88 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that no progression items can be put in Mithalas when option enabled
"""
from . import AquariaTestBase
from BaseClasses import ItemClassification
from ..Locations import AquariaLocationNames
class NoProgressionMithalasTest(AquariaTestBase):
"""Unit test used to test that no progression items can be put in Mithalas when option enabled"""
options = {
"no_progression_mithalas": True
}
unfillable_locations = [
AquariaLocationNames.MITHALAS_CITY_FIRST_BULB_IN_THE_LEFT_CITY_PART,
AquariaLocationNames.MITHALAS_CITY_SECOND_BULB_IN_THE_LEFT_CITY_PART,
AquariaLocationNames.MITHALAS_CITY_BULB_IN_THE_RIGHT_PART,
AquariaLocationNames.MITHALAS_CITY_BULB_AT_THE_TOP_OF_THE_CITY,
AquariaLocationNames.MITHALAS_CITY_FIRST_BULB_IN_A_BROKEN_HOME,
AquariaLocationNames.MITHALAS_CITY_SECOND_BULB_IN_A_BROKEN_HOME,
AquariaLocationNames.MITHALAS_CITY_BULB_IN_THE_BOTTOM_LEFT_PART,
AquariaLocationNames.MITHALAS_CITY_FIRST_BULB_IN_ONE_OF_THE_HOMES,
AquariaLocationNames.MITHALAS_CITY_SECOND_BULB_IN_ONE_OF_THE_HOMES,
AquariaLocationNames.MITHALAS_CITY_FIRST_URN_IN_ONE_OF_THE_HOMES,
AquariaLocationNames.MITHALAS_CITY_SECOND_URN_IN_ONE_OF_THE_HOMES,
AquariaLocationNames.MITHALAS_CITY_FIRST_URN_IN_THE_CITY_RESERVE,
AquariaLocationNames.MITHALAS_CITY_SECOND_URN_IN_THE_CITY_RESERVE,
AquariaLocationNames.MITHALAS_CITY_THIRD_URN_IN_THE_CITY_RESERVE,
AquariaLocationNames.MITHALAS_CITY_FIRST_BULB_AT_THE_END_OF_THE_TOP_PATH,
AquariaLocationNames.MITHALAS_CITY_SECOND_BULB_AT_THE_END_OF_THE_TOP_PATH,
AquariaLocationNames.MITHALAS_CITY_BULB_IN_THE_TOP_PATH,
AquariaLocationNames.MITHALAS_CITY_MITHALAS_POT,
AquariaLocationNames.MITHALAS_CITY_URN_IN_THE_CASTLE_FLOWER_TUBE_ENTRANCE,
AquariaLocationNames.MITHALAS_CITY_DOLL,
AquariaLocationNames.MITHALAS_CITY_URN_INSIDE_A_HOME_FISH_PASS,
AquariaLocationNames.MITHALAS_CITY_CASTLE_BULB_IN_THE_FLESH_HOLE,
AquariaLocationNames.MITHALAS_CITY_CASTLE_BLUE_BANNER,
AquariaLocationNames.MITHALAS_CITY_CASTLE_URN_IN_THE_BEDROOM,
AquariaLocationNames.MITHALAS_CITY_CASTLE_FIRST_URN_OF_THE_SINGLE_LAMP_PATH,
AquariaLocationNames.MITHALAS_CITY_CASTLE_SECOND_URN_OF_THE_SINGLE_LAMP_PATH,
AquariaLocationNames.MITHALAS_CITY_CASTLE_URN_IN_THE_BOTTOM_ROOM,
AquariaLocationNames.MITHALAS_CITY_CASTLE_FIRST_URN_ON_THE_ENTRANCE_PATH,
AquariaLocationNames.MITHALAS_CITY_CASTLE_SECOND_URN_ON_THE_ENTRANCE_PATH,
AquariaLocationNames.MITHALAS_CITY_CASTLE_BEATING_THE_PRIESTS,
AquariaLocationNames.MITHALAS_CITY_CASTLE_TRIDENT_HEAD,
AquariaLocationNames.MITHALAS_CATHEDRAL_FIRST_URN_IN_THE_TOP_RIGHT_ROOM,
AquariaLocationNames.MITHALAS_CATHEDRAL_SECOND_URN_IN_THE_TOP_RIGHT_ROOM,
AquariaLocationNames.MITHALAS_CATHEDRAL_THIRD_URN_IN_THE_TOP_RIGHT_ROOM,
AquariaLocationNames.MITHALAS_CATHEDRAL_BULB_IN_THE_FLESH_ROOM_WITH_FLEAS,
AquariaLocationNames.MITHALAS_CATHEDRAL_FIRST_URN_IN_THE_BOTTOM_RIGHT_PATH,
AquariaLocationNames.MITHALAS_CATHEDRAL_SECOND_URN_IN_THE_BOTTOM_RIGHT_PATH,
AquariaLocationNames.MITHALAS_CATHEDRAL_URN_BEHIND_THE_FLESH_VEIN,
AquariaLocationNames.MITHALAS_CATHEDRAL_URN_IN_THE_TOP_LEFT_EYES_BOSS_ROOM,
AquariaLocationNames.MITHALAS_CATHEDRAL_FIRST_URN_IN_THE_PATH_BEHIND_THE_FLESH_VEIN,
AquariaLocationNames.MITHALAS_CATHEDRAL_SECOND_URN_IN_THE_PATH_BEHIND_THE_FLESH_VEIN,
AquariaLocationNames.MITHALAS_CATHEDRAL_THIRD_URN_IN_THE_PATH_BEHIND_THE_FLESH_VEIN,
AquariaLocationNames.MITHALAS_CATHEDRAL_FOURTH_URN_IN_THE_TOP_RIGHT_ROOM,
AquariaLocationNames.MITHALAS_CATHEDRAL_MITHALAN_DRESS,
AquariaLocationNames.MITHALAS_CATHEDRAL_URN_BELOW_THE_LEFT_ENTRANCE,
AquariaLocationNames.CATHEDRAL_UNDERGROUND_BULB_IN_THE_CENTER_PART,
AquariaLocationNames.CATHEDRAL_UNDERGROUND_FIRST_BULB_IN_THE_TOP_LEFT_PART,
AquariaLocationNames.CATHEDRAL_UNDERGROUND_SECOND_BULB_IN_THE_TOP_LEFT_PART,
AquariaLocationNames.CATHEDRAL_UNDERGROUND_THIRD_BULB_IN_THE_TOP_LEFT_PART,
AquariaLocationNames.CATHEDRAL_UNDERGROUND_BULB_CLOSE_TO_THE_SAVE_CRYSTAL,
AquariaLocationNames.CATHEDRAL_UNDERGROUND_BULB_IN_THE_BOTTOM_RIGHT_PATH,
AquariaLocationNames.MITHALAS_BOSS_AREA_BEATING_MITHALAN_GOD,
]
def test_no_progression_mithalas(self) -> None:
"""
Unit test used to test that no progression items can be put in Mithalas when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
if item.classification == ItemClassification.progression:
self.assertFalse(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" can be filled with \"" + item_name + "\"")
else:
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -0,0 +1,38 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that no progression items can be put in Simon says when option enabled
"""
from . import AquariaTestBase
from BaseClasses import ItemClassification
from ..Locations import AquariaLocationNames
class NoProgressionSimonSaysTest(AquariaTestBase):
"""Unit test used to test that no progression items can be put in Simon says when option enabled"""
options = {
"no_progression_simon_says": True
}
unfillable_locations = [
AquariaLocationNames.SIMON_SAYS_AREA_BEATING_SIMON_SAYS,
AquariaLocationNames.SIMON_SAYS_AREA_TRANSTURTLE,
]
def test_no_progression_simon_says(self) -> None:
"""
Unit test used to test that no progression items can be put in Simon says when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
if item.classification == ItemClassification.progression:
self.assertFalse(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" can be filled with \"" + item_name + "\"")
else:
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -0,0 +1,67 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that no progression items can be put in the Veil when option enabled
"""
from . import AquariaTestBase
from BaseClasses import ItemClassification
from ..Locations import AquariaLocationNames
class NoProgressionVeilTest(AquariaTestBase):
"""Unit test used to test that no progression items can be put in the Veil when option enabled"""
options = {
"no_progression_veil": True
}
unfillable_locations = [
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_IN_LI_S_CAVE,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_BULB_UNDER_THE_ROCK_IN_THE_TOP_RIGHT_PATH,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_BULB_HIDDEN_BEHIND_THE_BLOCKING_ROCK,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_TRANSTURTLE,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_BULB_INSIDE_THE_FISH_PASS,
AquariaLocationNames.TURTLE_CAVE_TURTLE_EGG,
AquariaLocationNames.TURTLE_CAVE_BULB_IN_BUBBLE_CLIFF,
AquariaLocationNames.TURTLE_CAVE_URCHIN_COSTUME,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_BULB_IN_THE_MIDDLE_OF_THE_WALL_JUMP_CLIFF,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_GOLDEN_STARFISH,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_BULB_AT_THE_TOP_OF_THE_WATERFALL,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_TRANSTURTLE,
AquariaLocationNames.THE_VEIL_BOTTOM_AREA_BULB_IN_THE_LEFT_PATH,
AquariaLocationNames.THE_VEIL_BOTTOM_AREA_BULB_IN_THE_SPIRIT_PATH,
AquariaLocationNames.THE_VEIL_BOTTOM_AREA_VERSE_EGG,
AquariaLocationNames.THE_VEIL_BOTTOM_AREA_STONE_HEAD,
AquariaLocationNames.OCTOPUS_CAVE_DUMBO_EGG,
AquariaLocationNames.OCTOPUS_CAVE_BULB_IN_THE_PATH_BELOW_THE_OCTOPUS_CAVE_PATH,
AquariaLocationNames.SUN_TEMPLE_BULB_IN_THE_TOP_LEFT_PART,
AquariaLocationNames.SUN_TEMPLE_BULB_IN_THE_TOP_RIGHT_PART,
AquariaLocationNames.SUN_TEMPLE_BULB_AT_THE_TOP_OF_THE_HIGH_DARK_ROOM,
AquariaLocationNames.SUN_TEMPLE_GOLDEN_GEAR,
AquariaLocationNames.SUN_TEMPLE_FIRST_BULB_OF_THE_TEMPLE,
AquariaLocationNames.SUN_TEMPLE_BULB_ON_THE_RIGHT_PART,
AquariaLocationNames.SUN_TEMPLE_BULB_IN_THE_HIDDEN_ROOM_OF_THE_RIGHT_PART,
AquariaLocationNames.SUN_TEMPLE_SUN_KEY,
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_FIRST_PATH_BULB,
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_SECOND_PATH_BULB,
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_FIRST_CLIFF_BULB,
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_SECOND_CLIFF_BULB,
AquariaLocationNames.SUN_TEMPLE_BOSS_AREA_BEATING_LUMEREAN_GOD,
]
def test_no_progression_veil(self) -> None:
"""
Unit test used to test that no progression items can be put in the Veil when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
if item.classification == ItemClassification.progression:
self.assertFalse(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" can be filled with \"" + item_name + "\"")
else:
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -0,0 +1,37 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that progression items can be put in Arnassi Ruins area when option enabled
"""
from . import AquariaTestBase
from ..Locations import AquariaLocationNames
class ProgressionArnassiRuinsTest(AquariaTestBase):
"""Unit test used to test that progression items can be put in Arnassi Ruins area when option enabled"""
options = {
"no_progression_arnassi_ruins": False
}
unfillable_locations = [
AquariaLocationNames.ARNASSI_RUINS_BULB_IN_THE_RIGHT_PART,
AquariaLocationNames.ARNASSI_RUINS_BULB_IN_THE_LEFT_PART,
AquariaLocationNames.ARNASSI_RUINS_BULB_IN_THE_CENTER_PART,
AquariaLocationNames.ARNASSI_RUINS_SONG_PLANT_SPORE,
AquariaLocationNames.ARNASSI_RUINS_ARNASSI_ARMOR,
AquariaLocationNames.ARNASSI_RUINS_ARNASSI_STATUE,
AquariaLocationNames.ARNASSI_RUINS_TRANSTURTLE,
AquariaLocationNames.ARNASSI_RUINS_CRAB_ARMOR,
]
def test_progression_arnassi_ruins(self) -> None:
"""
Unit test used to test that progression items can be put in Arnassi Ruins area when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -0,0 +1,37 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that progression items can be put in Energy Temple area when option enabled
"""
from . import AquariaTestBase
from ..Locations import AquariaLocationNames
class ProgressionEnergyTempleTest(AquariaTestBase):
"""Unit test used to test that progression items can be put in Energy Temple area when option enabled"""
options = {
"no_progression_energy_temple": False
}
unfillable_locations = [
AquariaLocationNames.ENERGY_TEMPLE_FIRST_AREA_BEATING_THE_ENERGY_STATUE,
AquariaLocationNames.ENERGY_TEMPLE_FIRST_AREA_BULB_IN_THE_BOTTOM_ROOM_BLOCKED_BY_A_ROCK,
AquariaLocationNames.ENERGY_TEMPLE_ENERGY_IDOL,
AquariaLocationNames.ENERGY_TEMPLE_SECOND_AREA_BULB_UNDER_THE_ROCK,
AquariaLocationNames.ENERGY_TEMPLE_BOTTOM_ENTRANCE_KROTITE_ARMOR,
AquariaLocationNames.ENERGY_TEMPLE_THIRD_AREA_BULB_IN_THE_BOTTOM_PATH,
AquariaLocationNames.ENERGY_TEMPLE_BOSS_AREA_FALLEN_GOD_TOOTH,
AquariaLocationNames.ENERGY_TEMPLE_BLASTER_ROOM_BLASTER_EGG,
]
def test_progression_energy_temple(self) -> None:
"""
Unit test used to test that progression items can be put in Energy Temple area when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -0,0 +1,37 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that progression items can be put in Frozen Veil area when option enabled
"""
from . import AquariaTestBase
from ..Locations import AquariaLocationNames
class ProgressionFrozenVeilTest(AquariaTestBase):
"""Unit test used to test that progression items can be put in Frozen Veil area when option enabled"""
options = {
"no_progression_frozen_veil": False
}
unfillable_locations = [
AquariaLocationNames.ICE_CAVERN_BULB_IN_THE_ROOM_TO_THE_RIGHT,
AquariaLocationNames.ICE_CAVERN_FIRST_BULB_IN_THE_TOP_EXIT_ROOM,
AquariaLocationNames.ICE_CAVERN_SECOND_BULB_IN_THE_TOP_EXIT_ROOM,
AquariaLocationNames.ICE_CAVERN_THIRD_BULB_IN_THE_TOP_EXIT_ROOM,
AquariaLocationNames.ICE_CAVERN_BULB_IN_THE_LEFT_ROOM,
AquariaLocationNames.BUBBLE_CAVE_BULB_IN_THE_LEFT_CAVE_WALL,
AquariaLocationNames.BUBBLE_CAVE_BULB_IN_THE_RIGHT_CAVE_WALL_BEHIND_THE_ICE_CRYSTAL,
AquariaLocationNames.BUBBLE_CAVE_VERSE_EGG,
]
def test_progression_frozen_veil(self) -> None:
"""
Unit test used to test that progression items can be put in Frozen Veil area when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -8,7 +8,7 @@ from . import AquariaTestBase
from ..Locations import AquariaLocationNames
class UNoProgressionHardHiddenTest(AquariaTestBase):
class ProgressionHardHiddenTest(AquariaTestBase):
"""Unit test used to test that no progression items can be put in hard or hidden locations when option disabled"""
options = {
"no_progression_hard_or_hidden_locations": False
@@ -42,7 +42,7 @@ class UNoProgressionHardHiddenTest(AquariaTestBase):
AquariaLocationNames.ARNASSI_RUINS_ARNASSI_ARMOR,
]
def test_unconfine_home_water_both_location_fillable(self) -> None:
def test_progression_hard_or_hidden(self) -> None:
"""Unit test used to test that progression items can be put in hard or hidden locations when option disabled"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:

View File

@@ -0,0 +1,54 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that progression items can be put in Kelp Forest when option enabled
"""
from . import AquariaTestBase
from ..Locations import AquariaLocationNames
class ProgressionKelpForestTest(AquariaTestBase):
"""Unit test used to test that progression items can be put in Kelp Forest when option enabled"""
options = {
"no_progression_kelp_forest": False
}
unfillable_locations = [
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_BULB_IN_THE_BOTTOM_LEFT_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_BULB_IN_THE_PATH_DOWN_FROM_THE_TOP_LEFT_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_BULB_IN_THE_TOP_LEFT_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_JELLY_EGG,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_BULB_CLOSE_TO_THE_VERSE_EGG,
AquariaLocationNames.KELP_FOREST_TOP_LEFT_AREA_VERSE_EGG,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_UNDER_THE_ROCK_IN_THE_RIGHT_PATH,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_AT_THE_LEFT_OF_THE_CENTER_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_IN_THE_LEFT_PATH_S_BIG_ROOM,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_IN_THE_LEFT_PATH_S_SMALL_ROOM,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_AT_THE_TOP_OF_THE_CENTER_CLEARING,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BLACK_PEARL,
AquariaLocationNames.KELP_FOREST_TOP_RIGHT_AREA_BULB_IN_THE_TOP_FISH_PASS,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_BULB_CLOSE_TO_THE_SPIRIT_CRYSTALS,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_WALKER_BABY,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_TRANSTURTLE,
AquariaLocationNames.KELP_FOREST_BOTTOM_RIGHT_AREA_ODD_CONTAINER,
AquariaLocationNames.KELP_FOREST_BOSS_AREA_BEATING_DRUNIAN_GOD,
AquariaLocationNames.KELP_FOREST_BOSS_ROOM_BULB_AT_THE_BOTTOM_OF_THE_AREA,
AquariaLocationNames.KELP_FOREST_BOTTOM_LEFT_AREA_FISH_CAVE_PUZZLE,
AquariaLocationNames.KELP_FOREST_SPRITE_CAVE_BULB_INSIDE_THE_FISH_PASS,
AquariaLocationNames.KELP_FOREST_SPRITE_CAVE_BULB_IN_THE_SECOND_ROOM,
AquariaLocationNames.KELP_FOREST_SPRITE_CAVE_SEED_BAG,
AquariaLocationNames.MERMOG_CAVE_BULB_IN_THE_LEFT_PART_OF_THE_CAVE,
AquariaLocationNames.MERMOG_CAVE_PIRANHA_EGG,
]
def test_progression_kelp_forest(self) -> None:
"""
Unit test used to test that progression items can be put in Kelp Forest when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -0,0 +1,31 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that progression items can be put in Mithalas area when option enabled
"""
from . import AquariaTestBase
from ..Locations import AquariaLocationNames
class ProgressionMithalasTest(AquariaTestBase):
"""Unit test used to test that progression items can be put in Mithalas area when option enabled"""
options = {
"no_progression_mithalas": False
}
unfillable_locations = [
AquariaLocationNames.SIMON_SAYS_AREA_BEATING_SIMON_SAYS,
AquariaLocationNames.SIMON_SAYS_AREA_TRANSTURTLE,
]
def test_progression_mithalas(self) -> None:
"""
Unit test used to test that progression items can be put in Mithalas area when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -0,0 +1,31 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that progression items can be put in Simon says area when option enabled
"""
from . import AquariaTestBase
from ..Locations import AquariaLocationNames
class ProgressionSimonSaysTest(AquariaTestBase):
"""Unit test used to test that progression items can be put in Simon says area when option enabled"""
options = {
"no_progression_simon_says": False
}
unfillable_locations = [
AquariaLocationNames.SIMON_SAYS_AREA_BEATING_SIMON_SAYS,
AquariaLocationNames.SIMON_SAYS_AREA_TRANSTURTLE,
]
def test_progression_simon_says(self) -> None:
"""
Unit test used to test that progression items can be put in Simon says area when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -0,0 +1,60 @@
"""
Author: Louis M
Date: Fri, 03 May 2024 14:07:35 +0000
Description: Unit test used to test that progression items can be put in the Veil area when option enabled
"""
from . import AquariaTestBase
from ..Locations import AquariaLocationNames
class ProgressionVeilTest(AquariaTestBase):
"""Unit test used to test that progression items can be put in the Veil area when option enabled"""
options = {
"no_progression_veil": False
}
unfillable_locations = [
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_IN_LI_S_CAVE,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_BULB_UNDER_THE_ROCK_IN_THE_TOP_RIGHT_PATH,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_BULB_HIDDEN_BEHIND_THE_BLOCKING_ROCK,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_TRANSTURTLE,
AquariaLocationNames.THE_VEIL_TOP_LEFT_AREA_BULB_INSIDE_THE_FISH_PASS,
AquariaLocationNames.TURTLE_CAVE_TURTLE_EGG,
AquariaLocationNames.TURTLE_CAVE_BULB_IN_BUBBLE_CLIFF,
AquariaLocationNames.TURTLE_CAVE_URCHIN_COSTUME,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_BULB_IN_THE_MIDDLE_OF_THE_WALL_JUMP_CLIFF,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_GOLDEN_STARFISH,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_BULB_AT_THE_TOP_OF_THE_WATERFALL,
AquariaLocationNames.THE_VEIL_TOP_RIGHT_AREA_TRANSTURTLE,
AquariaLocationNames.THE_VEIL_BOTTOM_AREA_BULB_IN_THE_LEFT_PATH,
AquariaLocationNames.THE_VEIL_BOTTOM_AREA_BULB_IN_THE_SPIRIT_PATH,
AquariaLocationNames.THE_VEIL_BOTTOM_AREA_VERSE_EGG,
AquariaLocationNames.THE_VEIL_BOTTOM_AREA_STONE_HEAD,
AquariaLocationNames.OCTOPUS_CAVE_DUMBO_EGG,
AquariaLocationNames.OCTOPUS_CAVE_BULB_IN_THE_PATH_BELOW_THE_OCTOPUS_CAVE_PATH,
AquariaLocationNames.SUN_TEMPLE_BULB_IN_THE_TOP_LEFT_PART,
AquariaLocationNames.SUN_TEMPLE_BULB_IN_THE_TOP_RIGHT_PART,
AquariaLocationNames.SUN_TEMPLE_BULB_AT_THE_TOP_OF_THE_HIGH_DARK_ROOM,
AquariaLocationNames.SUN_TEMPLE_GOLDEN_GEAR,
AquariaLocationNames.SUN_TEMPLE_FIRST_BULB_OF_THE_TEMPLE,
AquariaLocationNames.SUN_TEMPLE_BULB_ON_THE_RIGHT_PART,
AquariaLocationNames.SUN_TEMPLE_BULB_IN_THE_HIDDEN_ROOM_OF_THE_RIGHT_PART,
AquariaLocationNames.SUN_TEMPLE_SUN_KEY,
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_FIRST_PATH_BULB,
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_SECOND_PATH_BULB,
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_FIRST_CLIFF_BULB,
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_SECOND_CLIFF_BULB,
AquariaLocationNames.SUN_TEMPLE_BOSS_AREA_BEATING_LUMEREAN_GOD,
]
def test_progression_veil(self) -> None:
"""
Unit test used to test that progression items can be put in the Veil area when option enabled
"""
for location in self.unfillable_locations:
for item_name in self.world.item_names:
item = self.get_item_by_name(item_name)
self.assertTrue(
self.world.get_location(location).can_fill(self.multiworld.state, item, False),
"The location \"" + location + "\" cannot be filled with \"" + item_name + "\"")

View File

@@ -0,0 +1,30 @@
"""
Author: Louis M
Date: Thu, 18 Apr 2024 18:45:56 +0000
Description: Unit test used to test accessibility of locations with and without the sun form with the goal four gods
"""
from . import AquariaTestBase
from ..Items import ItemNames
from ..Locations import AquariaLocationNames
from ..Options import UnconfineHomeWater, Objective
class SunFormFourGodsAccessTest(AquariaTestBase):
"""Unit test used to test accessibility of locations with and without the sun form with the goal four gods"""
options = {
"unconfine_home_water": UnconfineHomeWater.option_via_energy_door,
"objective": Objective.option_killing_the_four_gods
}
def test_sun_form_location(self) -> None:
"""Test locations that require sun form with the goal four gods"""
locations = [
AquariaLocationNames.OCTOPUS_CAVE_DUMBO_EGG,
AquariaLocationNames.BEATING_OCTOPUS_PRIME,
AquariaLocationNames.BEATING_THE_GOLEM,
AquariaLocationNames.SUNKEN_CITY_CLEARED
]
items = [[ItemNames.SUN_FORM]]
self.assertAccessDependency(locations, items, True)

View File

@@ -0,0 +1,29 @@
"""
Author: Louis M
Date: Sun, 06 Apr 2025 14:00:32 +0000
Description: Unit test used to test Sun Temple cliffs access
"""
from BaseClasses import CollectionState
from . import AquariaTestBase
from ..Items import ItemNames
from ..Options import UnconfineHomeWater
from ..Locations import AquariaLocationNames
class SunTempleCliffAccessTest(AquariaTestBase):
"""Unit test used to test Sun Temple cliffs access"""
options = {
"unconfine_home_water": UnconfineHomeWater.option_via_energy_door
}
def test_sun_temple_cliff_access(self) -> None:
"""test Sun Temple cliffs access"""
state = CollectionState(self.multiworld)
state.collect(self.get_item_by_name(ItemNames.BEAST_FORM))
state.collect(self.get_item_by_name(ItemNames.SUN_FORM))
first_cliff_location = self.multiworld.get_location(
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_FIRST_CLIFF_BULB, 1)
self.assertFalse(first_cliff_location.can_reach(state))
second_cliff_location = self.multiworld.get_location(
AquariaLocationNames.SUN_TEMPLE_BOSS_PATH_SECOND_CLIFF_BULB, 1)
self.assertFalse(second_cliff_location.can_reach(state))