mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-21 06:45:49 -07:00
Compare commits
2 Commits
plando-ite
...
plando-cou
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86a6939f02 | ||
|
|
51254948aa |
2
Fill.py
2
Fill.py
@@ -890,7 +890,7 @@ def parse_planned_blocks(multiworld: MultiWorld) -> dict[int, list[PlandoItemBlo
|
||||
worlds = set()
|
||||
for listed_world in target_world:
|
||||
if listed_world not in world_name_lookup:
|
||||
failed(f"Cannot place item to {listed_world}'s world as that world does not exist.",
|
||||
failed(f"Cannot place item to {target_world}'s world as that world does not exist.",
|
||||
block.force)
|
||||
continue
|
||||
worlds.add(world_name_lookup[listed_world])
|
||||
|
||||
@@ -548,12 +548,10 @@ def set_up_take_anys(multiworld, world, player):
|
||||
old_man_take_any.shop = TakeAny(old_man_take_any, 0x0112, 0xE2, True, True, total_shop_slots)
|
||||
multiworld.shops.append(old_man_take_any.shop)
|
||||
|
||||
sword_indices = [
|
||||
index for index, item in enumerate(multiworld.itempool) if item.player == player and item.type == 'Sword'
|
||||
]
|
||||
if sword_indices:
|
||||
sword_index = multiworld.random.choice(sword_indices)
|
||||
sword = multiworld.itempool.pop(sword_index)
|
||||
swords = [item for item in multiworld.itempool if item.player == player and item.type == 'Sword']
|
||||
if swords:
|
||||
sword = multiworld.random.choice(swords)
|
||||
multiworld.itempool.remove(sword)
|
||||
multiworld.itempool.append(item_factory('Rupees (20)', world))
|
||||
old_man_take_any.shop.add_inventory(0, sword.name, 0, 0)
|
||||
loc_name = "Old Man Sword Cave"
|
||||
|
||||
@@ -38,7 +38,7 @@ class DungeonFillTestBase(TestCase):
|
||||
def test_original_dungeons(self):
|
||||
self.generate_with_options(DungeonItem.option_original_dungeon)
|
||||
for location in self.multiworld.get_filled_locations():
|
||||
with (self.subTest(location_name=location.name)):
|
||||
with (self.subTest(location=location)):
|
||||
if location.parent_region.dungeon is None:
|
||||
self.assertIs(location.item.dungeon, None)
|
||||
else:
|
||||
@@ -52,7 +52,7 @@ class DungeonFillTestBase(TestCase):
|
||||
def test_own_dungeons(self):
|
||||
self.generate_with_options(DungeonItem.option_own_dungeons)
|
||||
for location in self.multiworld.get_filled_locations():
|
||||
with self.subTest(location_name=location.name):
|
||||
with self.subTest(location=location):
|
||||
if location.parent_region.dungeon is None:
|
||||
self.assertIs(location.item.dungeon, None)
|
||||
else:
|
||||
|
||||
@@ -4,7 +4,7 @@ Date: Fri, 15 Mar 2024 18:41:40 +0000
|
||||
Description: Used to manage Regions in the Aquaria game multiworld randomizer
|
||||
"""
|
||||
|
||||
from typing import Dict, Optional, Iterable
|
||||
from typing import Dict, Optional
|
||||
from BaseClasses import MultiWorld, Region, Entrance, Item, ItemClassification, CollectionState
|
||||
from .Items import AquariaItem, ItemNames
|
||||
from .Locations import AquariaLocations, AquariaLocation, AquariaLocationNames
|
||||
@@ -34,15 +34,10 @@ def _has_li(state: CollectionState, player: int) -> bool:
|
||||
return state.has(ItemNames.LI_AND_LI_SONG, player)
|
||||
|
||||
|
||||
DAMAGING_ITEMS:Iterable[str] = [
|
||||
ItemNames.ENERGY_FORM, ItemNames.NATURE_FORM, ItemNames.BEAST_FORM,
|
||||
ItemNames.LI_AND_LI_SONG, ItemNames.BABY_NAUTILUS, ItemNames.BABY_PIRANHA,
|
||||
ItemNames.BABY_BLASTER
|
||||
]
|
||||
|
||||
def _has_damaging_item(state: CollectionState, player: int, damaging_items:Iterable[str] = DAMAGING_ITEMS) -> bool:
|
||||
"""`player` in `state` has the an item that do damage other than the ones in `to_remove`"""
|
||||
return state.has_any(damaging_items, player)
|
||||
def _has_damaging_item(state: CollectionState, player: int) -> bool:
|
||||
"""`player` in `state` has the shield song item"""
|
||||
return state.has_any({ItemNames.ENERGY_FORM, ItemNames.NATURE_FORM, ItemNames.BEAST_FORM, ItemNames.LI_AND_LI_SONG,
|
||||
ItemNames.BABY_NAUTILUS, ItemNames.BABY_PIRANHA, ItemNames.BABY_BLASTER}, player)
|
||||
|
||||
|
||||
def _has_energy_attack_item(state: CollectionState, player: int) -> bool:
|
||||
@@ -571,11 +566,9 @@ class AquariaRegions:
|
||||
self.__connect_one_way_regions(self.openwater_tr, self.openwater_tr_turtle,
|
||||
lambda state: _has_beast_form_or_arnassi_armor(state, self.player))
|
||||
self.__connect_one_way_regions(self.openwater_tr_turtle, self.openwater_tr)
|
||||
damaging_items_minus_nature_form = [item for item in DAMAGING_ITEMS if item != ItemNames.NATURE_FORM]
|
||||
self.__connect_one_way_regions(self.openwater_tr, self.openwater_tr_urns,
|
||||
lambda state: _has_bind_song(state, self.player) or
|
||||
_has_damaging_item(state, self.player,
|
||||
damaging_items_minus_nature_form))
|
||||
_has_damaging_item(state, self.player))
|
||||
self.__connect_regions(self.openwater_tr, self.openwater_br)
|
||||
self.__connect_regions(self.openwater_tr, self.mithalas_city)
|
||||
self.__connect_regions(self.openwater_tr, self.veil_b)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import typing
|
||||
|
||||
from BaseClasses import MultiWorld
|
||||
from Options import OptionError
|
||||
from worlds.AutoWorld import World
|
||||
|
||||
from .Names import LocationName
|
||||
@@ -100,9 +99,8 @@ def get_gate_bosses(world: World):
|
||||
pass
|
||||
|
||||
if boss in plando_bosses:
|
||||
raise OptionError(f"Invalid input for option `plando_bosses`: "
|
||||
f"No Duplicate Bosses permitted ({boss}) - for "
|
||||
f"{world.player_name}")
|
||||
# TODO: Raise error here. Duplicates not allowed
|
||||
pass
|
||||
|
||||
plando_bosses[boss_num] = boss
|
||||
|
||||
@@ -110,14 +108,13 @@ def get_gate_bosses(world: World):
|
||||
available_bosses.remove(boss)
|
||||
|
||||
for x in range(world.options.number_of_level_gates):
|
||||
if (10 not in selected_bosses) and (king_boom_boo not in available_bosses) and ((x + 1) / world.options.number_of_level_gates) > 0.5:
|
||||
available_bosses.extend(gate_bosses_with_requirements_table.keys())
|
||||
if ("king boom boo" not in selected_bosses) and ("king boom boo" not in available_bosses) and ((x + 1) / world.options.number_of_level_gates) > 0.5:
|
||||
available_bosses.extend(gate_bosses_with_requirements_table)
|
||||
world.random.shuffle(available_bosses)
|
||||
|
||||
chosen_boss = available_bosses[0]
|
||||
if plando_bosses[x] != "None":
|
||||
if plando_bosses[x] not in available_bosses:
|
||||
available_bosses.append(plando_bosses[x])
|
||||
available_bosses.append(plando_bosses[x])
|
||||
chosen_boss = plando_bosses[x]
|
||||
|
||||
selected_bosses.append(all_gate_bosses_table[chosen_boss])
|
||||
|
||||
@@ -324,8 +324,7 @@ def set_mission_upgrade_rules_standard(multiworld: MultiWorld, world: World, pla
|
||||
add_rule_safe(multiworld, LocationName.iron_gate_5, player,
|
||||
lambda state: state.has(ItemName.eggman_large_cannon, player))
|
||||
add_rule_safe(multiworld, LocationName.dry_lagoon_5, player,
|
||||
lambda state: state.has(ItemName.rouge_pick_nails, player) and
|
||||
state.has(ItemName.rouge_treasure_scope, player))
|
||||
lambda state: state.has(ItemName.rouge_treasure_scope, player))
|
||||
add_rule_safe(multiworld, LocationName.sand_ocean_5, player,
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
add_rule_safe(multiworld, LocationName.egg_quarters_5, player,
|
||||
@@ -408,7 +407,8 @@ def set_mission_upgrade_rules_standard(multiworld: MultiWorld, world: World, pla
|
||||
lambda state: state.has(ItemName.sonic_bounce_bracelet, player))
|
||||
|
||||
add_rule(multiworld.get_location(LocationName.cosmic_wall_chao_1, player),
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
lambda state: state.has(ItemName.eggman_mystic_melody, player) and
|
||||
state.has(ItemName.eggman_jet_engine, player))
|
||||
|
||||
add_rule(multiworld.get_location(LocationName.cannon_core_chao_1, player),
|
||||
lambda state: state.has(ItemName.tails_booster, player) and
|
||||
@@ -1402,6 +1402,8 @@ def set_mission_upgrade_rules_standard(multiworld: MultiWorld, world: World, pla
|
||||
state.has(ItemName.eggman_large_cannon, player)))
|
||||
add_rule(multiworld.get_location(LocationName.dry_lagoon_lifebox_2, player),
|
||||
lambda state: state.has(ItemName.rouge_treasure_scope, player))
|
||||
add_rule(multiworld.get_location(LocationName.sand_ocean_lifebox_2, player),
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
add_rule(multiworld.get_location(LocationName.egg_quarters_lifebox_2, player),
|
||||
lambda state: (state.has(ItemName.rouge_mystic_melody, player) and
|
||||
state.has(ItemName.rouge_treasure_scope, player)))
|
||||
@@ -1722,9 +1724,6 @@ def set_mission_upgrade_rules_standard(multiworld: MultiWorld, world: World, pla
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
add_rule(multiworld.get_location(LocationName.white_jungle_itembox_8, player),
|
||||
lambda state: state.has(ItemName.shadow_air_shoes, player))
|
||||
add_rule(multiworld.get_location(LocationName.sky_rail_itembox_8, player),
|
||||
lambda state: (state.has(ItemName.shadow_air_shoes, player) and
|
||||
state.has(ItemName.shadow_mystic_melody, player)))
|
||||
add_rule(multiworld.get_location(LocationName.mad_space_itembox_8, player),
|
||||
lambda state: state.has(ItemName.rouge_iron_boots, player))
|
||||
add_rule(multiworld.get_location(LocationName.cosmic_wall_itembox_8, player),
|
||||
@@ -2309,7 +2308,8 @@ def set_mission_upgrade_rules_hard(multiworld: MultiWorld, world: World, player:
|
||||
lambda state: state.has(ItemName.tails_booster, player))
|
||||
|
||||
add_rule(multiworld.get_location(LocationName.cosmic_wall_chao_1, player),
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
lambda state: state.has(ItemName.eggman_mystic_melody, player) and
|
||||
state.has(ItemName.eggman_jet_engine, player))
|
||||
|
||||
add_rule(multiworld.get_location(LocationName.cannon_core_chao_1, player),
|
||||
lambda state: state.has(ItemName.tails_booster, player) and
|
||||
@@ -2980,6 +2980,8 @@ def set_mission_upgrade_rules_hard(multiworld: MultiWorld, world: World, player:
|
||||
state.has(ItemName.eggman_jet_engine, player)))
|
||||
add_rule(multiworld.get_location(LocationName.dry_lagoon_lifebox_2, player),
|
||||
lambda state: state.has(ItemName.rouge_treasure_scope, player))
|
||||
add_rule(multiworld.get_location(LocationName.sand_ocean_lifebox_2, player),
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
add_rule(multiworld.get_location(LocationName.egg_quarters_lifebox_2, player),
|
||||
lambda state: (state.has(ItemName.rouge_mystic_melody, player) and
|
||||
state.has(ItemName.rouge_treasure_scope, player)))
|
||||
@@ -3591,7 +3593,8 @@ def set_mission_upgrade_rules_expert(multiworld: MultiWorld, world: World, playe
|
||||
lambda state: state.has(ItemName.tails_booster, player))
|
||||
|
||||
add_rule(multiworld.get_location(LocationName.cosmic_wall_chao_1, player),
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
lambda state: state.has(ItemName.eggman_mystic_melody, player) and
|
||||
state.has(ItemName.eggman_jet_engine, player))
|
||||
|
||||
add_rule(multiworld.get_location(LocationName.cannon_core_chao_1, player),
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player) and
|
||||
@@ -3640,6 +3643,9 @@ def set_mission_upgrade_rules_expert(multiworld: MultiWorld, world: World, playe
|
||||
add_rule(multiworld.get_location(LocationName.cosmic_wall_pipe_2, player),
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
|
||||
add_rule(multiworld.get_location(LocationName.cannon_core_pipe_2, player),
|
||||
lambda state: state.has(ItemName.tails_booster, player))
|
||||
|
||||
add_rule(multiworld.get_location(LocationName.prison_lane_pipe_3, player),
|
||||
lambda state: state.has(ItemName.tails_bazooka, player))
|
||||
add_rule(multiworld.get_location(LocationName.mission_street_pipe_3, player),
|
||||
@@ -3765,6 +3771,10 @@ def set_mission_upgrade_rules_expert(multiworld: MultiWorld, world: World, playe
|
||||
add_rule(multiworld.get_location(LocationName.cosmic_wall_beetle, player),
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
|
||||
add_rule(multiworld.get_location(LocationName.cannon_core_beetle, player),
|
||||
lambda state: state.has(ItemName.tails_booster, player) and
|
||||
state.has(ItemName.knuckles_hammer_gloves, player))
|
||||
|
||||
# Animal Upgrade Requirements
|
||||
if world.options.animalsanity:
|
||||
add_rule(multiworld.get_location(LocationName.hidden_base_animal_2, player),
|
||||
@@ -3829,7 +3839,8 @@ def set_mission_upgrade_rules_expert(multiworld: MultiWorld, world: World, playe
|
||||
add_rule(multiworld.get_location(LocationName.weapons_bed_animal_8, player),
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
add_rule(multiworld.get_location(LocationName.security_hall_animal_8, player),
|
||||
lambda state: state.has(ItemName.rouge_iron_boots, player))
|
||||
lambda state: state.has(ItemName.rouge_pick_nails, player) and
|
||||
state.has(ItemName.rouge_iron_boots, player))
|
||||
add_rule(multiworld.get_location(LocationName.cosmic_wall_animal_8, player),
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
|
||||
@@ -3965,6 +3976,8 @@ def set_mission_upgrade_rules_expert(multiworld: MultiWorld, world: World, playe
|
||||
state.has(ItemName.tails_bazooka, player))
|
||||
add_rule(multiworld.get_location(LocationName.crazy_gadget_animal_16, player),
|
||||
lambda state: state.has(ItemName.sonic_flame_ring, player))
|
||||
add_rule(multiworld.get_location(LocationName.final_rush_animal_16, player),
|
||||
lambda state: state.has(ItemName.sonic_bounce_bracelet, player))
|
||||
|
||||
add_rule(multiworld.get_location(LocationName.final_chase_animal_17, player),
|
||||
lambda state: state.has(ItemName.shadow_flame_ring, player))
|
||||
@@ -4022,6 +4035,8 @@ def set_mission_upgrade_rules_expert(multiworld: MultiWorld, world: World, playe
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
add_rule(multiworld.get_location(LocationName.dry_lagoon_lifebox_2, player),
|
||||
lambda state: state.has(ItemName.rouge_treasure_scope, player))
|
||||
add_rule(multiworld.get_location(LocationName.sand_ocean_lifebox_2, player),
|
||||
lambda state: state.has(ItemName.eggman_jet_engine, player))
|
||||
add_rule(multiworld.get_location(LocationName.egg_quarters_lifebox_2, player),
|
||||
lambda state: state.has(ItemName.rouge_treasure_scope, player))
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ from .Constants import *
|
||||
|
||||
def launch_client(*args: str):
|
||||
from .Client import launch
|
||||
launch_subprocess(launch, name=CLIENT_NAME, args=args)
|
||||
launch_subprocess(launch(*args), name=CLIENT_NAME)
|
||||
|
||||
|
||||
components.append(
|
||||
|
||||
@@ -271,11 +271,11 @@ solar_essence = BundleItem(Loot.solar_essence)
|
||||
void_essence = BundleItem(Loot.void_essence)
|
||||
|
||||
petrified_slime = BundleItem(Mineral.petrified_slime)
|
||||
blue_slime_egg = BundleItem(AnimalProduct.slime_egg_blue)
|
||||
red_slime_egg = BundleItem(AnimalProduct.slime_egg_red)
|
||||
purple_slime_egg = BundleItem(AnimalProduct.slime_egg_purple)
|
||||
green_slime_egg = BundleItem(AnimalProduct.slime_egg_green)
|
||||
tiger_slime_egg = BundleItem(AnimalProduct.slime_egg_tiger, source=BundleItem.Sources.island)
|
||||
blue_slime_egg = BundleItem(Loot.blue_slime_egg)
|
||||
red_slime_egg = BundleItem(Loot.red_slime_egg)
|
||||
purple_slime_egg = BundleItem(Loot.purple_slime_egg)
|
||||
green_slime_egg = BundleItem(Loot.green_slime_egg)
|
||||
tiger_slime_egg = BundleItem(Loot.tiger_slime_egg, source=BundleItem.Sources.island)
|
||||
|
||||
cherry_bomb = BundleItem(Bomb.cherry_bomb, 5)
|
||||
bomb = BundleItem(Bomb.bomb, 2)
|
||||
|
||||
@@ -168,16 +168,15 @@ class StardewLogic(ReceivedLogicMixin, HasLogicMixin, RegionLogicMixin, Travelin
|
||||
AnimalProduct.squid_ink: self.mine.can_mine_in_the_mines_floor_81_120() | (self.building.has_building(Building.fish_pond) & self.has(Fish.squid)),
|
||||
AnimalProduct.sturgeon_roe: self.has(Fish.sturgeon) & self.building.has_building(Building.fish_pond),
|
||||
AnimalProduct.truffle: self.animal.has_animal(Animal.pig) & self.season.has_any_not_winter(),
|
||||
AnimalProduct.void_egg: self.has(AnimalProduct.void_egg_starter), # Should also check void chicken if there was an alternative to obtain it without void egg
|
||||
AnimalProduct.void_egg: self.has(AnimalProduct.void_egg_starter), # Should also check void chicken if there was an alternative to obtain it without void egg
|
||||
AnimalProduct.wool: self.animal.has_animal(Animal.rabbit) | self.animal.has_animal(Animal.sheep),
|
||||
AnimalProduct.slime_egg_green: self.has(Machine.slime_egg_press) & self.has(Loot.slime),
|
||||
AnimalProduct.slime_egg_blue: self.has(Machine.slime_egg_press) & self.has(Loot.slime) & self.time.has_lived_months(3),
|
||||
AnimalProduct.slime_egg_red: self.has(Machine.slime_egg_press) & self.has(Loot.slime) & self.time.has_lived_months(6),
|
||||
AnimalProduct.slime_egg_purple: self.has(Machine.slime_egg_press) & self.has(Loot.slime) & self.time.has_lived_months(9),
|
||||
AnimalProduct.slime_egg_tiger: self.can_fish_pond(Fish.lionfish, *(Forageable.ginger, Fruit.pineapple, Fruit.mango)) & self.time.has_lived_months(12) &
|
||||
self.building.has_building(Building.slime_hutch) & self.monster.can_kill(Monster.tiger_slime),
|
||||
AnimalProduct.duck_egg_starter: self.logic.false_, # It could be purchased at the Feast of the Winter Star, but it's random every year, so not considering it yet...
|
||||
AnimalProduct.dinosaur_egg_starter: self.logic.false_, # Dinosaur eggs are also part of the museum rules, and I don't want to touch them yet.
|
||||
AnimalProduct.slime_egg_tiger: self.has(Fish.lionfish) & self.building.has_building(Building.fish_pond),
|
||||
AnimalProduct.duck_egg_starter: self.logic.false_, # It could be purchased at the Feast of the Winter Star, but it's random every year, so not considering it yet...
|
||||
AnimalProduct.dinosaur_egg_starter: self.logic.false_, # Dinosaur eggs are also part of the museum rules, and I don't want to touch them yet.
|
||||
AnimalProduct.egg_starter: self.logic.false_, # It could be purchased at the Desert Festival, but festival logic is quite a mess, so not considering it yet...
|
||||
AnimalProduct.golden_egg_starter: self.received(AnimalProduct.golden_egg) & (self.money.can_spend_at(Region.ranch, 100000) | self.money.can_trade_at(Region.qi_walnut_room, Currency.qi_gem, 100)),
|
||||
AnimalProduct.void_egg_starter: self.money.can_spend_at(Region.sewer, 5000) | (self.building.has_building(Building.fish_pond) & self.has(Fish.void_salmon)),
|
||||
@@ -234,7 +233,7 @@ class StardewLogic(ReceivedLogicMixin, HasLogicMixin, RegionLogicMixin, Travelin
|
||||
Forageable.secret_note: self.quest.has_magnifying_glass() & (self.ability.can_chop_trees() | self.mine.can_mine_in_the_mines_floor_1_40()), #
|
||||
Fossil.bone_fragment: (self.region.can_reach(Region.dig_site) & self.tool.has_tool(Tool.pickaxe)) | self.monster.can_kill(Monster.skeleton),
|
||||
Fossil.fossilized_leg: self.region.can_reach(Region.dig_site) & self.tool.has_tool(Tool.pickaxe),
|
||||
Fossil.fossilized_ribs: self.region.can_reach(Region.island_south) & self.tool.has_tool(Tool.hoe) & self.received("Open Professor Snail Cave"),
|
||||
Fossil.fossilized_ribs: self.region.can_reach(Region.island_south) & self.tool.has_tool(Tool.hoe),
|
||||
Fossil.fossilized_skull: self.action.can_open_geode(Geode.golden_coconut),
|
||||
Fossil.fossilized_spine: self.fishing.can_fish_at(Region.dig_site),
|
||||
Fossil.fossilized_tail: self.action.can_pan_at(Region.dig_site, ToolMaterial.copper),
|
||||
@@ -289,9 +288,9 @@ class StardewLogic(ReceivedLogicMixin, HasLogicMixin, RegionLogicMixin, Travelin
|
||||
MetalBar.quartz: self.can_smelt(Mineral.quartz) | self.can_smelt("Fire Quartz") | (self.has(Machine.recycling_machine) & (self.has(Trash.broken_cd) | self.has(Trash.broken_glasses))),
|
||||
MetalBar.radioactive: self.can_smelt(Ore.radioactive),
|
||||
Ore.copper: self.mine.can_mine_in_the_mines_floor_1_40() | self.mine.can_mine_in_the_skull_cavern() | self.tool.has_tool(Tool.pan, ToolMaterial.copper),
|
||||
Ore.gold: self.mine.can_mine_in_the_mines_floor_81_120() | self.mine.can_mine_in_the_skull_cavern() | self.tool.has_tool(Tool.pan, ToolMaterial.gold),
|
||||
Ore.iridium: self.count(2, *(self.mine.can_mine_in_the_skull_cavern(), self.can_fish_pond(Fish.super_cucumber), self.tool.has_tool(Tool.pan, ToolMaterial.iridium))),
|
||||
Ore.iron: self.mine.can_mine_in_the_mines_floor_41_80() | self.mine.can_mine_in_the_skull_cavern() | self.tool.has_tool(Tool.pan, ToolMaterial.iron),
|
||||
Ore.gold: self.mine.can_mine_in_the_mines_floor_81_120() | self.mine.can_mine_in_the_skull_cavern() | self.tool.has_tool(Tool.pan, ToolMaterial.iron),
|
||||
Ore.iridium: self.mine.can_mine_in_the_skull_cavern() | self.can_fish_pond(Fish.super_cucumber) | self.tool.has_tool(Tool.pan, ToolMaterial.gold),
|
||||
Ore.iron: self.mine.can_mine_in_the_mines_floor_41_80() | self.mine.can_mine_in_the_skull_cavern() | self.tool.has_tool(Tool.pan, ToolMaterial.copper),
|
||||
Ore.radioactive: self.ability.can_mine_perfectly() & self.region.can_reach(Region.qi_walnut_room),
|
||||
RetainingSoil.basic: self.money.can_spend_at(Region.pierre_store, 100),
|
||||
RetainingSoil.quality: self.time.has_year_two & self.money.can_spend_at(Region.pierre_store, 150),
|
||||
@@ -382,8 +381,5 @@ class StardewLogic(ReceivedLogicMixin, HasLogicMixin, RegionLogicMixin, Travelin
|
||||
def can_use_obelisk(self, obelisk: str) -> StardewRule:
|
||||
return self.region.can_reach(Region.farm) & self.received(obelisk)
|
||||
|
||||
def can_fish_pond(self, fish: str, *items: str) -> StardewRule:
|
||||
rule = self.building.has_building(Building.fish_pond) & self.has(fish)
|
||||
if items:
|
||||
rule = rule & self.has_all(*items)
|
||||
return rule
|
||||
def can_fish_pond(self, fish: str) -> StardewRule:
|
||||
return self.building.has_building(Building.fish_pond) & self.has(fish)
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
class Loot:
|
||||
blue_slime_egg = "Blue Slime Egg"
|
||||
red_slime_egg = "Red Slime Egg"
|
||||
purple_slime_egg = "Purple Slime Egg"
|
||||
green_slime_egg = "Green Slime Egg"
|
||||
tiger_slime_egg = "Tiger Slime Egg"
|
||||
slime = "Slime"
|
||||
bug_meat = "Bug Meat"
|
||||
bat_wing = "Bat Wing"
|
||||
|
||||
@@ -11,7 +11,7 @@ class EntranceRandomizationAssertMixin:
|
||||
non_progression_connections = [connection for connection in all_connections.values() if RandomizationFlag.BIT_NON_PROGRESSION in connection.flag]
|
||||
|
||||
for non_progression_connections in non_progression_connections:
|
||||
with self.subTest(connection=non_progression_connections.name):
|
||||
with self.subTest(connection=non_progression_connections):
|
||||
self.assert_can_reach_entrance(non_progression_connections.name)
|
||||
|
||||
|
||||
|
||||
@@ -12,14 +12,14 @@ from ...regions.regions import create_all_regions, create_all_connections
|
||||
class TestVanillaRegionsConnectionsWithGingerIsland(unittest.TestCase):
|
||||
def test_region_exits_lead_somewhere(self):
|
||||
for region in vanilla_data.regions_with_ginger_island_by_name.values():
|
||||
with self.subTest(region=region.name):
|
||||
with self.subTest(region=region):
|
||||
for exit_ in region.exits:
|
||||
self.assertIn(exit_, vanilla_data.connections_with_ginger_island_by_name,
|
||||
f"{region.name} is leading to {exit_} but it does not exist.")
|
||||
|
||||
def test_connection_lead_somewhere(self):
|
||||
for connection in vanilla_data.connections_with_ginger_island_by_name.values():
|
||||
with self.subTest(connection=connection.name):
|
||||
with self.subTest(connection=connection):
|
||||
self.assertIn(connection.destination, vanilla_data.regions_with_ginger_island_by_name,
|
||||
f"{connection.name} is leading to {connection.destination} but it does not exist.")
|
||||
|
||||
@@ -27,14 +27,14 @@ class TestVanillaRegionsConnectionsWithGingerIsland(unittest.TestCase):
|
||||
class TestVanillaRegionsConnectionsWithoutGingerIsland(unittest.TestCase):
|
||||
def test_region_exits_lead_somewhere(self):
|
||||
for region in vanilla_data.regions_without_ginger_island_by_name.values():
|
||||
with self.subTest(region=region.name):
|
||||
with self.subTest(region=region):
|
||||
for exit_ in region.exits:
|
||||
self.assertIn(exit_, vanilla_data.connections_without_ginger_island_by_name,
|
||||
f"{region.name} is leading to {exit_} but it does not exist.")
|
||||
|
||||
def test_connection_lead_somewhere(self):
|
||||
for connection in vanilla_data.connections_without_ginger_island_by_name.values():
|
||||
with self.subTest(connection=connection.name):
|
||||
with self.subTest(connection=connection):
|
||||
self.assertIn(connection.destination, vanilla_data.regions_without_ginger_island_by_name,
|
||||
f"{connection.name} is leading to {connection.destination} but it does not exist.")
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ class TestNeedRegionToCatchFish(SVTestBase):
|
||||
SeasonRandomization.internal_name: SeasonRandomization.option_disabled,
|
||||
ElevatorProgression.internal_name: ElevatorProgression.option_vanilla,
|
||||
SkillProgression.internal_name: SkillProgression.option_vanilla,
|
||||
ToolProgression.internal_name: ToolProgression.option_progressive,
|
||||
ToolProgression.internal_name: ToolProgression.option_vanilla,
|
||||
Fishsanity.internal_name: Fishsanity.option_all,
|
||||
ExcludeGingerIsland.internal_name: ExcludeGingerIsland.option_false,
|
||||
SpecialOrderLocations.internal_name: SpecialOrderLocations.option_board_qi,
|
||||
@@ -18,7 +18,7 @@ class TestNeedRegionToCatchFish(SVTestBase):
|
||||
fish_and_items = {
|
||||
Fish.crimsonfish: ["Beach Bridge"],
|
||||
Fish.void_salmon: ["Railroad Boulder Removed", "Dark Talisman"],
|
||||
Fish.woodskip: ["Progressive Axe", "Progressive Axe", "Progressive Weapon"], # For the ores to get the axe upgrades
|
||||
Fish.woodskip: ["Glittering Boulder Removed", "Progressive Weapon"], # For the ores to get the axe upgrades
|
||||
Fish.mutant_carp: ["Rusty Key"],
|
||||
Fish.slimejack: ["Railroad Boulder Removed", "Rusty Key"],
|
||||
Fish.lionfish: ["Boat Repair"],
|
||||
@@ -26,8 +26,8 @@ class TestNeedRegionToCatchFish(SVTestBase):
|
||||
Fish.stingray: ["Boat Repair", "Island Resort"],
|
||||
Fish.ghostfish: ["Progressive Weapon"],
|
||||
Fish.stonefish: ["Progressive Weapon"],
|
||||
Fish.ice_pip: ["Progressive Weapon", "Progressive Weapon", "Progressive Pickaxe", "Progressive Pickaxe"],
|
||||
Fish.lava_eel: ["Progressive Weapon", "Progressive Weapon", "Progressive Weapon", "Progressive Pickaxe", "Progressive Pickaxe", "Progressive Pickaxe"],
|
||||
Fish.ice_pip: ["Progressive Weapon", "Progressive Weapon"],
|
||||
Fish.lava_eel: ["Progressive Weapon", "Progressive Weapon", "Progressive Weapon"],
|
||||
Fish.sandfish: ["Bus Repair"],
|
||||
Fish.scorpion_carp: ["Desert Obelisk"],
|
||||
# Starting the extended family quest requires having caught all the legendaries before, so they all have the rules of every other legendary
|
||||
@@ -37,7 +37,6 @@ class TestNeedRegionToCatchFish(SVTestBase):
|
||||
Fish.legend_ii: ["Beach Bridge", "Island Obelisk", "Island West Turtle", "Qi Walnut Room", "Rusty Key"],
|
||||
Fish.ms_angler: ["Beach Bridge", "Island Obelisk", "Island West Turtle", "Qi Walnut Room", "Rusty Key"],
|
||||
}
|
||||
self.collect("Progressive Fishing Rod", 4)
|
||||
self.original_state = self.multiworld.state.copy()
|
||||
for fish in fish_and_items:
|
||||
with self.subTest(f"Region rules for {fish}"):
|
||||
|
||||
Reference in New Issue
Block a user