Minecraft: Update to new options system. (#3765)
* Move to new options system. switch to using self.random reformat rules file. * further reformats * fix tests to use new options system. * fix slot data to not use self.multiworld * I hate python * new starting_items docstring to prepare for 1.20.5+ item components. fix invalid json being output to starting_items * more typing fixes. * stupid quotes around type declarations * removed unused variable in ItemPool.py change null check in Structures.py * update rules "self" variable to a "world: MinecraftWorld" variable * get key, and not value for required bosses.
This commit is contained in:
parent
1e8a8e7482
commit
c010c8c938
|
@ -1,10 +1,14 @@
|
||||||
from math import ceil
|
from math import ceil
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from BaseClasses import MultiWorld, Item
|
from BaseClasses import Item
|
||||||
from worlds.AutoWorld import World
|
|
||||||
|
|
||||||
from . import Constants
|
from . import Constants
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from . import MinecraftWorld
|
||||||
|
|
||||||
|
|
||||||
def get_junk_item_names(rand, k: int) -> str:
|
def get_junk_item_names(rand, k: int) -> str:
|
||||||
junk_weights = Constants.item_info["junk_weights"]
|
junk_weights = Constants.item_info["junk_weights"]
|
||||||
|
@ -14,39 +18,38 @@ def get_junk_item_names(rand, k: int) -> str:
|
||||||
k=k)
|
k=k)
|
||||||
return junk
|
return junk
|
||||||
|
|
||||||
def build_item_pool(mc_world: World) -> List[Item]:
|
def build_item_pool(world: "MinecraftWorld") -> List[Item]:
|
||||||
multiworld = mc_world.multiworld
|
multiworld = world.multiworld
|
||||||
player = mc_world.player
|
player = world.player
|
||||||
|
|
||||||
itempool = []
|
itempool = []
|
||||||
total_location_count = len(multiworld.get_unfilled_locations(player))
|
total_location_count = len(multiworld.get_unfilled_locations(player))
|
||||||
|
|
||||||
required_pool = Constants.item_info["required_pool"]
|
required_pool = Constants.item_info["required_pool"]
|
||||||
junk_weights = Constants.item_info["junk_weights"]
|
|
||||||
|
|
||||||
# Add required progression items
|
# Add required progression items
|
||||||
for item_name, num in required_pool.items():
|
for item_name, num in required_pool.items():
|
||||||
itempool += [mc_world.create_item(item_name) for _ in range(num)]
|
itempool += [world.create_item(item_name) for _ in range(num)]
|
||||||
|
|
||||||
# Add structure compasses
|
# Add structure compasses
|
||||||
if multiworld.structure_compasses[player]:
|
if world.options.structure_compasses:
|
||||||
compasses = [name for name in mc_world.item_name_to_id if "Structure Compass" in name]
|
compasses = [name for name in world.item_name_to_id if "Structure Compass" in name]
|
||||||
for item_name in compasses:
|
for item_name in compasses:
|
||||||
itempool.append(mc_world.create_item(item_name))
|
itempool.append(world.create_item(item_name))
|
||||||
|
|
||||||
# Dragon egg shards
|
# Dragon egg shards
|
||||||
if multiworld.egg_shards_required[player] > 0:
|
if world.options.egg_shards_required > 0:
|
||||||
num = multiworld.egg_shards_available[player]
|
num = world.options.egg_shards_available
|
||||||
itempool += [mc_world.create_item("Dragon Egg Shard") for _ in range(num)]
|
itempool += [world.create_item("Dragon Egg Shard") for _ in range(num)]
|
||||||
|
|
||||||
# Bee traps
|
# Bee traps
|
||||||
bee_trap_percentage = multiworld.bee_traps[player] * 0.01
|
bee_trap_percentage = world.options.bee_traps * 0.01
|
||||||
if bee_trap_percentage > 0:
|
if bee_trap_percentage > 0:
|
||||||
bee_trap_qty = ceil(bee_trap_percentage * (total_location_count - len(itempool)))
|
bee_trap_qty = ceil(bee_trap_percentage * (total_location_count - len(itempool)))
|
||||||
itempool += [mc_world.create_item("Bee Trap") for _ in range(bee_trap_qty)]
|
itempool += [world.create_item("Bee Trap") for _ in range(bee_trap_qty)]
|
||||||
|
|
||||||
# Fill remaining itempool with randomly generated junk
|
# Fill remaining itempool with randomly generated junk
|
||||||
junk = get_junk_item_names(multiworld.random, total_location_count - len(itempool))
|
junk = get_junk_item_names(world.random, total_location_count - len(itempool))
|
||||||
itempool += [mc_world.create_item(name) for name in junk]
|
itempool += [world.create_item(name) for name in junk]
|
||||||
|
|
||||||
return itempool
|
return itempool
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import typing
|
from Options import Choice, Toggle, DefaultOnToggle, Range, OptionList, DeathLink, PlandoConnections, \
|
||||||
from Options import Choice, Option, Toggle, DefaultOnToggle, Range, OptionList, DeathLink, PlandoConnections
|
PerGameCommonOptions
|
||||||
from .Constants import region_info
|
from .Constants import region_info
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
class AdvancementGoal(Range):
|
class AdvancementGoal(Range):
|
||||||
|
@ -55,7 +56,7 @@ class StructureCompasses(DefaultOnToggle):
|
||||||
display_name = "Structure Compasses"
|
display_name = "Structure Compasses"
|
||||||
|
|
||||||
|
|
||||||
class BeeTraps(Range):
|
class BeeTraps(Range):
|
||||||
"""Replaces a percentage of junk items with bee traps, which spawn multiple angered bees around every player when
|
"""Replaces a percentage of junk items with bee traps, which spawn multiple angered bees around every player when
|
||||||
received."""
|
received."""
|
||||||
display_name = "Bee Trap Percentage"
|
display_name = "Bee Trap Percentage"
|
||||||
|
@ -94,7 +95,20 @@ class SendDefeatedMobs(Toggle):
|
||||||
|
|
||||||
|
|
||||||
class StartingItems(OptionList):
|
class StartingItems(OptionList):
|
||||||
"""Start with these items. Each entry should be of this format: {item: "item_name", amount: #, nbt: "nbt_string"}"""
|
"""Start with these items. Each entry should be of this format: {item: "item_name", amount: #}
|
||||||
|
`item` can include components, and should be in an identical format to a `/give` command with
|
||||||
|
`"` escaped for json reasons.
|
||||||
|
|
||||||
|
`amount` is optional and will default to 1 if omitted.
|
||||||
|
|
||||||
|
example:
|
||||||
|
```
|
||||||
|
starting_items: [
|
||||||
|
{ "item": "minecraft:stick[minecraft:custom_name=\"{'text':'pointy stick'}\"]" },
|
||||||
|
{ "item": "minecraft:arrow[minecraft:rarity=epic]", amount: 64 }
|
||||||
|
]
|
||||||
|
```
|
||||||
|
"""
|
||||||
display_name = "Starting Items"
|
display_name = "Starting Items"
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,22 +123,21 @@ class MCPlandoConnections(PlandoConnections):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
minecraft_options: typing.Dict[str, type(Option)] = {
|
@dataclass
|
||||||
"plando_connections": MCPlandoConnections,
|
class MinecraftOptions(PerGameCommonOptions):
|
||||||
"advancement_goal": AdvancementGoal,
|
plando_connections: MCPlandoConnections
|
||||||
"egg_shards_required": EggShardsRequired,
|
advancement_goal: AdvancementGoal
|
||||||
"egg_shards_available": EggShardsAvailable,
|
egg_shards_required: EggShardsRequired
|
||||||
"required_bosses": BossGoal,
|
egg_shards_available: EggShardsAvailable
|
||||||
|
required_bosses: BossGoal
|
||||||
|
shuffle_structures: ShuffleStructures
|
||||||
|
structure_compasses: StructureCompasses
|
||||||
|
|
||||||
"shuffle_structures": ShuffleStructures,
|
combat_difficulty: CombatDifficulty
|
||||||
"structure_compasses": StructureCompasses,
|
include_hard_advancements: HardAdvancements
|
||||||
|
include_unreasonable_advancements: UnreasonableAdvancements
|
||||||
"combat_difficulty": CombatDifficulty,
|
include_postgame_advancements: PostgameAdvancements
|
||||||
"include_hard_advancements": HardAdvancements,
|
bee_traps: BeeTraps
|
||||||
"include_unreasonable_advancements": UnreasonableAdvancements,
|
send_defeated_mobs: SendDefeatedMobs
|
||||||
"include_postgame_advancements": PostgameAdvancements,
|
death_link: DeathLink
|
||||||
"bee_traps": BeeTraps,
|
starting_items: StartingItems
|
||||||
"send_defeated_mobs": SendDefeatedMobs,
|
|
||||||
"death_link": DeathLink,
|
|
||||||
"starting_items": StartingItems,
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,276 +1,471 @@
|
||||||
import typing
|
|
||||||
from collections.abc import Callable
|
|
||||||
|
|
||||||
from BaseClasses import CollectionState
|
from BaseClasses import CollectionState
|
||||||
from worlds.generic.Rules import exclusion_rules
|
from worlds.generic.Rules import exclusion_rules
|
||||||
from worlds.AutoWorld import World
|
|
||||||
|
|
||||||
from . import Constants
|
from . import Constants
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from . import MinecraftWorld
|
||||||
|
|
||||||
|
|
||||||
# Helper functions
|
# Helper functions
|
||||||
# moved from logicmixin
|
# moved from logicmixin
|
||||||
|
|
||||||
def has_iron_ingots(state: CollectionState, player: int) -> bool:
|
def has_iron_ingots(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
return state.has('Progressive Tools', player) and state.has('Progressive Resource Crafting', player)
|
return state.has('Progressive Tools', player) and state.has('Progressive Resource Crafting', player)
|
||||||
|
|
||||||
def has_copper_ingots(state: CollectionState, player: int) -> bool:
|
|
||||||
|
def has_copper_ingots(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
return state.has('Progressive Tools', player) and state.has('Progressive Resource Crafting', player)
|
return state.has('Progressive Tools', player) and state.has('Progressive Resource Crafting', player)
|
||||||
|
|
||||||
def has_gold_ingots(state: CollectionState, player: int) -> bool:
|
|
||||||
return state.has('Progressive Resource Crafting', player) and (state.has('Progressive Tools', player, 2) or state.can_reach('The Nether', 'Region', player))
|
|
||||||
|
|
||||||
def has_diamond_pickaxe(state: CollectionState, player: int) -> bool:
|
def has_gold_ingots(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
return state.has('Progressive Tools', player, 3) and has_iron_ingots(state, player)
|
return (state.has('Progressive Resource Crafting', player)
|
||||||
|
and (
|
||||||
|
state.has('Progressive Tools', player, 2)
|
||||||
|
or state.can_reach_region('The Nether', player)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def craft_crossbow(state: CollectionState, player: int) -> bool:
|
|
||||||
return state.has('Archery', player) and has_iron_ingots(state, player)
|
|
||||||
|
|
||||||
def has_bottle(state: CollectionState, player: int) -> bool:
|
def has_diamond_pickaxe(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
|
return state.has('Progressive Tools', player, 3) and has_iron_ingots(world, state, player)
|
||||||
|
|
||||||
|
|
||||||
|
def craft_crossbow(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
|
return state.has('Archery', player) and has_iron_ingots(world, state, player)
|
||||||
|
|
||||||
|
|
||||||
|
def has_bottle(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
return state.has('Bottles', player) and state.has('Progressive Resource Crafting', player)
|
return state.has('Bottles', player) and state.has('Progressive Resource Crafting', player)
|
||||||
|
|
||||||
def has_spyglass(state: CollectionState, player: int) -> bool:
|
|
||||||
return has_copper_ingots(state, player) and state.has('Spyglass', player) and can_adventure(state, player)
|
|
||||||
|
|
||||||
def can_enchant(state: CollectionState, player: int) -> bool:
|
def has_spyglass(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
return state.has('Enchanting', player) and has_diamond_pickaxe(state, player) # mine obsidian and lapis
|
return (has_copper_ingots(world, state, player)
|
||||||
|
and state.has('Spyglass', player)
|
||||||
|
and can_adventure(world, state, player)
|
||||||
|
)
|
||||||
|
|
||||||
def can_use_anvil(state: CollectionState, player: int) -> bool:
|
|
||||||
return state.has('Enchanting', player) and state.has('Progressive Resource Crafting', player, 2) and has_iron_ingots(state, player)
|
|
||||||
|
|
||||||
def fortress_loot(state: CollectionState, player: int) -> bool: # saddles, blaze rods, wither skulls
|
def can_enchant(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
return state.can_reach('Nether Fortress', 'Region', player) and basic_combat(state, player)
|
return state.has('Enchanting', player) and has_diamond_pickaxe(world, state, player) # mine obsidian and lapis
|
||||||
|
|
||||||
def can_brew_potions(state: CollectionState, player: int) -> bool:
|
|
||||||
return state.has('Blaze Rods', player) and state.has('Brewing', player) and has_bottle(state, player)
|
|
||||||
|
|
||||||
def can_piglin_trade(state: CollectionState, player: int) -> bool:
|
def can_use_anvil(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
return has_gold_ingots(state, player) and (
|
return (state.has('Enchanting', player)
|
||||||
state.can_reach('The Nether', 'Region', player) or
|
and state.has('Progressive Resource Crafting', player,2)
|
||||||
state.can_reach('Bastion Remnant', 'Region', player))
|
and has_iron_ingots(world, state, player)
|
||||||
|
)
|
||||||
|
|
||||||
def overworld_villager(state: CollectionState, player: int) -> bool:
|
|
||||||
|
def fortress_loot(world: "MinecraftWorld", state: CollectionState, player: int) -> bool: # saddles, blaze rods, wither skulls
|
||||||
|
return state.can_reach_region('Nether Fortress', player) and basic_combat(world, state, player)
|
||||||
|
|
||||||
|
|
||||||
|
def can_brew_potions(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
|
return state.has('Blaze Rods', player) and state.has('Brewing', player) and has_bottle(world, state, player)
|
||||||
|
|
||||||
|
|
||||||
|
def can_piglin_trade(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
|
return (has_gold_ingots(world, state, player)
|
||||||
|
and (
|
||||||
|
state.can_reach_region('The Nether', player)
|
||||||
|
or state.can_reach_region('Bastion Remnant', player)
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
def overworld_villager(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
village_region = state.multiworld.get_region('Village', player).entrances[0].parent_region.name
|
village_region = state.multiworld.get_region('Village', player).entrances[0].parent_region.name
|
||||||
if village_region == 'The Nether': # 2 options: cure zombie villager or build portal in village
|
if village_region == 'The Nether': # 2 options: cure zombie villager or build portal in village
|
||||||
return (state.can_reach('Zombie Doctor', 'Location', player) or
|
return (state.can_reach_location('Zombie Doctor', player)
|
||||||
(has_diamond_pickaxe(state, player) and state.can_reach('Village', 'Region', player)))
|
or (
|
||||||
|
has_diamond_pickaxe(world, state, player)
|
||||||
|
and state.can_reach_region('Village', player)
|
||||||
|
))
|
||||||
elif village_region == 'The End':
|
elif village_region == 'The End':
|
||||||
return state.can_reach('Zombie Doctor', 'Location', player)
|
return state.can_reach_location('Zombie Doctor', player)
|
||||||
return state.can_reach('Village', 'Region', player)
|
return state.can_reach_region('Village', player)
|
||||||
|
|
||||||
def enter_stronghold(state: CollectionState, player: int) -> bool:
|
|
||||||
|
def enter_stronghold(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
return state.has('Blaze Rods', player) and state.has('Brewing', player) and state.has('3 Ender Pearls', player)
|
return state.has('Blaze Rods', player) and state.has('Brewing', player) and state.has('3 Ender Pearls', player)
|
||||||
|
|
||||||
|
|
||||||
# Difficulty-dependent functions
|
# Difficulty-dependent functions
|
||||||
def combat_difficulty(state: CollectionState, player: int) -> bool:
|
def combat_difficulty(world: "MinecraftWorld", state: CollectionState, player: int) -> str:
|
||||||
return state.multiworld.combat_difficulty[player].current_key
|
return world.options.combat_difficulty.current_key
|
||||||
|
|
||||||
def can_adventure(state: CollectionState, player: int) -> bool:
|
|
||||||
death_link_check = not state.multiworld.death_link[player] or state.has('Bed', player)
|
def can_adventure(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
if combat_difficulty(state, player) == 'easy':
|
death_link_check = not world.options.death_link or state.has('Bed', player)
|
||||||
return state.has('Progressive Weapons', player, 2) and has_iron_ingots(state, player) and death_link_check
|
if combat_difficulty(world, state, player) == 'easy':
|
||||||
elif combat_difficulty(state, player) == 'hard':
|
return state.has('Progressive Weapons', player, 2) and has_iron_ingots(world, state, player) and death_link_check
|
||||||
|
elif combat_difficulty(world, state, player) == 'hard':
|
||||||
return True
|
return True
|
||||||
return (state.has('Progressive Weapons', player) and death_link_check and
|
return (state.has('Progressive Weapons', player) and death_link_check and
|
||||||
(state.has('Progressive Resource Crafting', player) or state.has('Campfire', player)))
|
(state.has('Progressive Resource Crafting', player) or state.has('Campfire', player)))
|
||||||
|
|
||||||
def basic_combat(state: CollectionState, player: int) -> bool:
|
|
||||||
if combat_difficulty(state, player) == 'easy':
|
def basic_combat(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
return state.has('Progressive Weapons', player, 2) and state.has('Progressive Armor', player) and \
|
if combat_difficulty(world, state, player) == 'easy':
|
||||||
state.has('Shield', player) and has_iron_ingots(state, player)
|
return (state.has('Progressive Weapons', player, 2)
|
||||||
elif combat_difficulty(state, player) == 'hard':
|
and state.has('Progressive Armor', player)
|
||||||
|
and state.has('Shield', player)
|
||||||
|
and has_iron_ingots(world, state, player)
|
||||||
|
)
|
||||||
|
elif combat_difficulty(world, state, player) == 'hard':
|
||||||
return True
|
return True
|
||||||
return state.has('Progressive Weapons', player) and (state.has('Progressive Armor', player) or state.has('Shield', player)) and has_iron_ingots(state, player)
|
return (state.has('Progressive Weapons', player)
|
||||||
|
and (
|
||||||
|
state.has('Progressive Armor', player)
|
||||||
|
or state.has('Shield', player)
|
||||||
|
)
|
||||||
|
and has_iron_ingots(world, state, player)
|
||||||
|
)
|
||||||
|
|
||||||
def complete_raid(state: CollectionState, player: int) -> bool:
|
|
||||||
reach_regions = state.can_reach('Village', 'Region', player) and state.can_reach('Pillager Outpost', 'Region', player)
|
|
||||||
if combat_difficulty(state, player) == 'easy':
|
|
||||||
return reach_regions and \
|
|
||||||
state.has('Progressive Weapons', player, 3) and state.has('Progressive Armor', player, 2) and \
|
|
||||||
state.has('Shield', player) and state.has('Archery', player) and \
|
|
||||||
state.has('Progressive Tools', player, 2) and has_iron_ingots(state, player)
|
|
||||||
elif combat_difficulty(state, player) == 'hard': # might be too hard?
|
|
||||||
return reach_regions and state.has('Progressive Weapons', player, 2) and has_iron_ingots(state, player) and \
|
|
||||||
(state.has('Progressive Armor', player) or state.has('Shield', player))
|
|
||||||
return reach_regions and state.has('Progressive Weapons', player, 2) and has_iron_ingots(state, player) and \
|
|
||||||
state.has('Progressive Armor', player) and state.has('Shield', player)
|
|
||||||
|
|
||||||
def can_kill_wither(state: CollectionState, player: int) -> bool:
|
def complete_raid(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
normal_kill = state.has("Progressive Weapons", player, 3) and state.has("Progressive Armor", player, 2) and can_brew_potions(state, player) and can_enchant(state, player)
|
reach_regions = (state.can_reach_region('Village', player)
|
||||||
if combat_difficulty(state, player) == 'easy':
|
and state.can_reach_region('Pillager Outpost', player))
|
||||||
return fortress_loot(state, player) and normal_kill and state.has('Archery', player)
|
if combat_difficulty(world, state, player) == 'easy':
|
||||||
elif combat_difficulty(state, player) == 'hard': # cheese kill using bedrock ceilings
|
return (reach_regions
|
||||||
return fortress_loot(state, player) and (normal_kill or state.can_reach('The Nether', 'Region', player) or state.can_reach('The End', 'Region', player))
|
and state.has('Progressive Weapons', player, 3)
|
||||||
return fortress_loot(state, player) and normal_kill
|
and state.has('Progressive Armor', player, 2)
|
||||||
|
and state.has('Shield', player)
|
||||||
|
and state.has('Archery', player)
|
||||||
|
and state.has('Progressive Tools', player, 2)
|
||||||
|
and has_iron_ingots(world, state, player)
|
||||||
|
)
|
||||||
|
elif combat_difficulty(world, state, player) == 'hard': # might be too hard?
|
||||||
|
return (reach_regions
|
||||||
|
and state.has('Progressive Weapons', player, 2)
|
||||||
|
and has_iron_ingots(world, state, player)
|
||||||
|
and (
|
||||||
|
state.has('Progressive Armor', player)
|
||||||
|
or state.has('Shield', player)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return (reach_regions
|
||||||
|
and state.has('Progressive Weapons', player, 2)
|
||||||
|
and has_iron_ingots(world, state, player)
|
||||||
|
and state.has('Progressive Armor', player)
|
||||||
|
and state.has('Shield', player)
|
||||||
|
)
|
||||||
|
|
||||||
def can_respawn_ender_dragon(state: CollectionState, player: int) -> bool:
|
|
||||||
return state.can_reach('The Nether', 'Region', player) and state.can_reach('The End', 'Region', player) and \
|
|
||||||
state.has('Progressive Resource Crafting', player) # smelt sand into glass
|
|
||||||
|
|
||||||
def can_kill_ender_dragon(state: CollectionState, player: int) -> bool:
|
def can_kill_wither(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
if combat_difficulty(state, player) == 'easy':
|
normal_kill = (state.has("Progressive Weapons", player, 3)
|
||||||
return state.has("Progressive Weapons", player, 3) and state.has("Progressive Armor", player, 2) and \
|
and state.has("Progressive Armor", player, 2)
|
||||||
state.has('Archery', player) and can_brew_potions(state, player) and can_enchant(state, player)
|
and can_brew_potions(world, state, player)
|
||||||
if combat_difficulty(state, player) == 'hard':
|
and can_enchant(world, state, player)
|
||||||
return (state.has('Progressive Weapons', player, 2) and state.has('Progressive Armor', player)) or \
|
)
|
||||||
(state.has('Progressive Weapons', player, 1) and state.has('Bed', player))
|
if combat_difficulty(world, state, player) == 'easy':
|
||||||
return state.has('Progressive Weapons', player, 2) and state.has('Progressive Armor', player) and state.has('Archery', player)
|
return (fortress_loot(world, state, player)
|
||||||
|
and normal_kill
|
||||||
|
and state.has('Archery', player)
|
||||||
|
)
|
||||||
|
elif combat_difficulty(world, state, player) == 'hard': # cheese kill using bedrock ceilings
|
||||||
|
return (fortress_loot(world, state, player)
|
||||||
|
and (
|
||||||
|
normal_kill
|
||||||
|
or state.can_reach_region('The Nether', player)
|
||||||
|
or state.can_reach_region('The End', player)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def has_structure_compass(state: CollectionState, entrance_name: str, player: int) -> bool:
|
return fortress_loot(world, state, player) and normal_kill
|
||||||
if not state.multiworld.structure_compasses[player]:
|
|
||||||
|
|
||||||
|
def can_respawn_ender_dragon(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
|
return (state.can_reach_region('The Nether', player)
|
||||||
|
and state.can_reach_region('The End', player)
|
||||||
|
and state.has('Progressive Resource Crafting', player) # smelt sand into glass
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def can_kill_ender_dragon(world: "MinecraftWorld", state: CollectionState, player: int) -> bool:
|
||||||
|
if combat_difficulty(world, state, player) == 'easy':
|
||||||
|
return (state.has("Progressive Weapons", player, 3)
|
||||||
|
and state.has("Progressive Armor", player, 2)
|
||||||
|
and state.has('Archery', player)
|
||||||
|
and can_brew_potions(world, state, player)
|
||||||
|
and can_enchant(world, state, player)
|
||||||
|
)
|
||||||
|
if combat_difficulty(world, state, player) == 'hard':
|
||||||
|
return (
|
||||||
|
(
|
||||||
|
state.has('Progressive Weapons', player, 2)
|
||||||
|
and state.has('Progressive Armor', player)
|
||||||
|
) or (
|
||||||
|
state.has('Progressive Weapons', player, 1)
|
||||||
|
and state.has('Bed', player) # who needs armor when you can respawn right outside the chamber
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return (state.has('Progressive Weapons', player, 2)
|
||||||
|
and state.has('Progressive Armor', player)
|
||||||
|
and state.has('Archery', player)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def has_structure_compass(world: "MinecraftWorld", state: CollectionState, entrance_name: str, player: int) -> bool:
|
||||||
|
if not world.options.structure_compasses:
|
||||||
return True
|
return True
|
||||||
return state.has(f"Structure Compass ({state.multiworld.get_entrance(entrance_name, player).connected_region.name})", player)
|
return state.has(f"Structure Compass ({state.multiworld.get_entrance(entrance_name, player).connected_region.name})", player)
|
||||||
|
|
||||||
|
|
||||||
def get_rules_lookup(player: int):
|
def get_rules_lookup(world, player: int):
|
||||||
rules_lookup: typing.Dict[str, typing.List[Callable[[CollectionState], bool]]] = {
|
rules_lookup = {
|
||||||
"entrances": {
|
"entrances": {
|
||||||
"Nether Portal": lambda state: (state.has('Flint and Steel', player) and
|
"Nether Portal": lambda state: state.has('Flint and Steel', player)
|
||||||
(state.has('Bucket', player) or state.has('Progressive Tools', player, 3)) and
|
and (
|
||||||
has_iron_ingots(state, player)),
|
state.has('Bucket', player)
|
||||||
"End Portal": lambda state: enter_stronghold(state, player) and state.has('3 Ender Pearls', player, 4),
|
or state.has('Progressive Tools', player, 3)
|
||||||
"Overworld Structure 1": lambda state: (can_adventure(state, player) and has_structure_compass(state, "Overworld Structure 1", player)),
|
)
|
||||||
"Overworld Structure 2": lambda state: (can_adventure(state, player) and has_structure_compass(state, "Overworld Structure 2", player)),
|
and has_iron_ingots(world, state, player),
|
||||||
"Nether Structure 1": lambda state: (can_adventure(state, player) and has_structure_compass(state, "Nether Structure 1", player)),
|
"End Portal": lambda state: enter_stronghold(world, state, player)
|
||||||
"Nether Structure 2": lambda state: (can_adventure(state, player) and has_structure_compass(state, "Nether Structure 2", player)),
|
and state.has('3 Ender Pearls', player, 4),
|
||||||
"The End Structure": lambda state: (can_adventure(state, player) and has_structure_compass(state, "The End Structure", player)),
|
"Overworld Structure 1": lambda state: can_adventure(world, state, player)
|
||||||
|
and has_structure_compass(world, state, "Overworld Structure 1", player),
|
||||||
|
"Overworld Structure 2": lambda state: can_adventure(world, state, player)
|
||||||
|
and has_structure_compass(world, state, "Overworld Structure 2", player),
|
||||||
|
"Nether Structure 1": lambda state: can_adventure(world, state, player)
|
||||||
|
and has_structure_compass(world, state, "Nether Structure 1", player),
|
||||||
|
"Nether Structure 2": lambda state: can_adventure(world, state, player)
|
||||||
|
and has_structure_compass(world, state, "Nether Structure 2", player),
|
||||||
|
"The End Structure": lambda state: can_adventure(world, state, player)
|
||||||
|
and has_structure_compass(world, state, "The End Structure", player),
|
||||||
},
|
},
|
||||||
"locations": {
|
"locations": {
|
||||||
"Ender Dragon": lambda state: can_respawn_ender_dragon(state, player) and can_kill_ender_dragon(state, player),
|
"Ender Dragon": lambda state: can_respawn_ender_dragon(world, state, player)
|
||||||
"Wither": lambda state: can_kill_wither(state, player),
|
and can_kill_ender_dragon(world, state, player),
|
||||||
"Blaze Rods": lambda state: fortress_loot(state, player),
|
"Wither": lambda state: can_kill_wither(world, state, player),
|
||||||
|
"Blaze Rods": lambda state: fortress_loot(world, state, player),
|
||||||
"Who is Cutting Onions?": lambda state: can_piglin_trade(state, player),
|
"Who is Cutting Onions?": lambda state: can_piglin_trade(world, state, player),
|
||||||
"Oh Shiny": lambda state: can_piglin_trade(state, player),
|
"Oh Shiny": lambda state: can_piglin_trade(world, state, player),
|
||||||
"Suit Up": lambda state: state.has("Progressive Armor", player) and has_iron_ingots(state, player),
|
"Suit Up": lambda state: state.has("Progressive Armor", player)
|
||||||
"Very Very Frightening": lambda state: (state.has("Channeling Book", player) and
|
and has_iron_ingots(world, state, player),
|
||||||
can_use_anvil(state, player) and can_enchant(state, player) and overworld_villager(state, player)),
|
"Very Very Frightening": lambda state: state.has("Channeling Book", player)
|
||||||
"Hot Stuff": lambda state: state.has("Bucket", player) and has_iron_ingots(state, player),
|
and can_use_anvil(world, state, player)
|
||||||
"Free the End": lambda state: can_respawn_ender_dragon(state, player) and can_kill_ender_dragon(state, player),
|
and can_enchant(world, state, player)
|
||||||
"A Furious Cocktail": lambda state: (can_brew_potions(state, player) and
|
and overworld_villager(world, state, player),
|
||||||
state.has("Fishing Rod", player) and # Water Breathing
|
"Hot Stuff": lambda state: state.has("Bucket", player)
|
||||||
state.can_reach("The Nether", "Region", player) and # Regeneration, Fire Resistance, gold nuggets
|
and has_iron_ingots(world, state, player),
|
||||||
state.can_reach("Village", "Region", player) and # Night Vision, Invisibility
|
"Free the End": lambda state: can_respawn_ender_dragon(world, state, player)
|
||||||
state.can_reach("Bring Home the Beacon", "Location", player)), # Resistance
|
and can_kill_ender_dragon(world, state, player),
|
||||||
"Bring Home the Beacon": lambda state: (can_kill_wither(state, player) and
|
"A Furious Cocktail": lambda state: (can_brew_potions(world, state, player)
|
||||||
has_diamond_pickaxe(state, player) and state.has("Progressive Resource Crafting", player, 2)),
|
and state.has("Fishing Rod", player) # Water Breathing
|
||||||
"Not Today, Thank You": lambda state: state.has("Shield", player) and has_iron_ingots(state, player),
|
and state.can_reach_region("The Nether", player) # Regeneration, Fire Resistance, gold nuggets
|
||||||
"Isn't It Iron Pick": lambda state: state.has("Progressive Tools", player, 2) and has_iron_ingots(state, player),
|
and state.can_reach_region("Village", player) # Night Vision, Invisibility
|
||||||
"Local Brewery": lambda state: can_brew_potions(state, player),
|
and state.can_reach_location("Bring Home the Beacon", player)),
|
||||||
"The Next Generation": lambda state: can_respawn_ender_dragon(state, player) and can_kill_ender_dragon(state, player),
|
# Resistance
|
||||||
|
"Bring Home the Beacon": lambda state: can_kill_wither(world, state, player)
|
||||||
|
and has_diamond_pickaxe(world, state, player)
|
||||||
|
and state.has("Progressive Resource Crafting", player, 2),
|
||||||
|
"Not Today, Thank You": lambda state: state.has("Shield", player)
|
||||||
|
and has_iron_ingots(world, state, player),
|
||||||
|
"Isn't It Iron Pick": lambda state: state.has("Progressive Tools", player, 2)
|
||||||
|
and has_iron_ingots(world, state, player),
|
||||||
|
"Local Brewery": lambda state: can_brew_potions(world, state, player),
|
||||||
|
"The Next Generation": lambda state: can_respawn_ender_dragon(world, state, player)
|
||||||
|
and can_kill_ender_dragon(world, state, player),
|
||||||
"Fishy Business": lambda state: state.has("Fishing Rod", player),
|
"Fishy Business": lambda state: state.has("Fishing Rod", player),
|
||||||
"This Boat Has Legs": lambda state: ((fortress_loot(state, player) or complete_raid(state, player)) and
|
"This Boat Has Legs": lambda state: (
|
||||||
state.has("Saddle", player) and state.has("Fishing Rod", player)),
|
fortress_loot(world, state, player)
|
||||||
|
or complete_raid(world, state, player)
|
||||||
|
)
|
||||||
|
and state.has("Saddle", player)
|
||||||
|
and state.has("Fishing Rod", player),
|
||||||
"Sniper Duel": lambda state: state.has("Archery", player),
|
"Sniper Duel": lambda state: state.has("Archery", player),
|
||||||
"Great View From Up Here": lambda state: basic_combat(state, player),
|
"Great View From Up Here": lambda state: basic_combat(world, state, player),
|
||||||
"How Did We Get Here?": lambda state: (can_brew_potions(state, player) and
|
"How Did We Get Here?": lambda state: (can_brew_potions(world, state, player)
|
||||||
has_gold_ingots(state, player) and # Absorption
|
and has_gold_ingots(world, state, player) # Absorption
|
||||||
state.can_reach('End City', 'Region', player) and # Levitation
|
and state.can_reach_region('End City', player) # Levitation
|
||||||
state.can_reach('The Nether', 'Region', player) and # potion ingredients
|
and state.can_reach_region('The Nether', player) # potion ingredients
|
||||||
state.has("Fishing Rod", player) and state.has("Archery",player) and # Pufferfish, Nautilus Shells; spectral arrows
|
and state.has("Fishing Rod", player) # Pufferfish, Nautilus Shells; spectral arrows
|
||||||
state.can_reach("Bring Home the Beacon", "Location", player) and # Haste
|
and state.has("Archery", player)
|
||||||
state.can_reach("Hero of the Village", "Location", player)), # Bad Omen, Hero of the Village
|
and state.can_reach_location("Bring Home the Beacon", player) # Haste
|
||||||
"Bullseye": lambda state: (state.has("Archery", player) and state.has("Progressive Tools", player, 2) and
|
and state.can_reach_location("Hero of the Village", player)), # Bad Omen, Hero of the Village
|
||||||
has_iron_ingots(state, player)),
|
"Bullseye": lambda state: state.has("Archery", player)
|
||||||
"Spooky Scary Skeleton": lambda state: basic_combat(state, player),
|
and state.has("Progressive Tools", player, 2)
|
||||||
"Two by Two": lambda state: has_iron_ingots(state, player) and state.has("Bucket", player) and can_adventure(state, player),
|
and has_iron_ingots(world, state, player),
|
||||||
"Two Birds, One Arrow": lambda state: craft_crossbow(state, player) and can_enchant(state, player),
|
"Spooky Scary Skeleton": lambda state: basic_combat(world, state, player),
|
||||||
"Who's the Pillager Now?": lambda state: craft_crossbow(state, player),
|
"Two by Two": lambda state: has_iron_ingots(world, state, player)
|
||||||
|
and state.has("Bucket", player)
|
||||||
|
and can_adventure(world, state, player),
|
||||||
|
"Two Birds, One Arrow": lambda state: craft_crossbow(world, state, player)
|
||||||
|
and can_enchant(world, state, player),
|
||||||
|
"Who's the Pillager Now?": lambda state: craft_crossbow(world, state, player),
|
||||||
"Getting an Upgrade": lambda state: state.has("Progressive Tools", player),
|
"Getting an Upgrade": lambda state: state.has("Progressive Tools", player),
|
||||||
"Tactical Fishing": lambda state: state.has("Bucket", player) and has_iron_ingots(state, player),
|
"Tactical Fishing": lambda state: state.has("Bucket", player)
|
||||||
"Zombie Doctor": lambda state: can_brew_potions(state, player) and has_gold_ingots(state, player),
|
and has_iron_ingots(world, state, player),
|
||||||
"Ice Bucket Challenge": lambda state: has_diamond_pickaxe(state, player),
|
"Zombie Doctor": lambda state: can_brew_potions(world, state, player)
|
||||||
"Into Fire": lambda state: basic_combat(state, player),
|
and has_gold_ingots(world, state, player),
|
||||||
"War Pigs": lambda state: basic_combat(state, player),
|
"Ice Bucket Challenge": lambda state: has_diamond_pickaxe(world, state, player),
|
||||||
|
"Into Fire": lambda state: basic_combat(world, state, player),
|
||||||
|
"War Pigs": lambda state: basic_combat(world, state, player),
|
||||||
"Take Aim": lambda state: state.has("Archery", player),
|
"Take Aim": lambda state: state.has("Archery", player),
|
||||||
"Total Beelocation": lambda state: state.has("Silk Touch Book", player) and can_use_anvil(state, player) and can_enchant(state, player),
|
"Total Beelocation": lambda state: state.has("Silk Touch Book", player)
|
||||||
"Arbalistic": lambda state: (craft_crossbow(state, player) and state.has("Piercing IV Book", player) and
|
and can_use_anvil(world, state, player)
|
||||||
can_use_anvil(state, player) and can_enchant(state, player)),
|
and can_enchant(world, state, player),
|
||||||
"The End... Again...": lambda state: can_respawn_ender_dragon(state, player) and can_kill_ender_dragon(state, player),
|
"Arbalistic": lambda state: (craft_crossbow(world, state, player)
|
||||||
"Acquire Hardware": lambda state: has_iron_ingots(state, player),
|
and state.has("Piercing IV Book", player)
|
||||||
"Not Quite \"Nine\" Lives": lambda state: can_piglin_trade(state, player) and state.has("Progressive Resource Crafting", player, 2),
|
and can_use_anvil(world, state, player)
|
||||||
"Cover Me With Diamonds": lambda state: (state.has("Progressive Armor", player, 2) and
|
and can_enchant(world, state, player)
|
||||||
state.has("Progressive Tools", player, 2) and has_iron_ingots(state, player)),
|
),
|
||||||
"Sky's the Limit": lambda state: basic_combat(state, player),
|
"The End... Again...": lambda state: can_respawn_ender_dragon(world, state, player)
|
||||||
"Hired Help": lambda state: state.has("Progressive Resource Crafting", player, 2) and has_iron_ingots(state, player),
|
and can_kill_ender_dragon(world, state, player),
|
||||||
"Sweet Dreams": lambda state: state.has("Bed", player) or state.can_reach('Village', 'Region', player),
|
"Acquire Hardware": lambda state: has_iron_ingots(world, state, player),
|
||||||
"You Need a Mint": lambda state: can_respawn_ender_dragon(state, player) and has_bottle(state, player),
|
"Not Quite \"Nine\" Lives": lambda state: can_piglin_trade(world, state, player)
|
||||||
"Monsters Hunted": lambda state: (can_respawn_ender_dragon(state, player) and can_kill_ender_dragon(state, player) and
|
and state.has("Progressive Resource Crafting", player, 2),
|
||||||
can_kill_wither(state, player) and state.has("Fishing Rod", player)),
|
"Cover Me With Diamonds": lambda state: state.has("Progressive Armor", player, 2)
|
||||||
"Enchanter": lambda state: can_enchant(state, player),
|
and state.has("Progressive Tools", player, 2)
|
||||||
"Voluntary Exile": lambda state: basic_combat(state, player),
|
and has_iron_ingots(world, state, player),
|
||||||
"Eye Spy": lambda state: enter_stronghold(state, player),
|
"Sky's the Limit": lambda state: basic_combat(world, state, player),
|
||||||
"Serious Dedication": lambda state: (can_brew_potions(state, player) and state.has("Bed", player) and
|
"Hired Help": lambda state: state.has("Progressive Resource Crafting", player, 2)
|
||||||
has_diamond_pickaxe(state, player) and has_gold_ingots(state, player)),
|
and has_iron_ingots(world, state, player),
|
||||||
"Postmortal": lambda state: complete_raid(state, player),
|
"Sweet Dreams": lambda state: state.has("Bed", player)
|
||||||
"Adventuring Time": lambda state: can_adventure(state, player),
|
or state.can_reach_region('Village', player),
|
||||||
"Hero of the Village": lambda state: complete_raid(state, player),
|
"You Need a Mint": lambda state: can_respawn_ender_dragon(world, state, player)
|
||||||
"Hidden in the Depths": lambda state: can_brew_potions(state, player) and state.has("Bed", player) and has_diamond_pickaxe(state, player),
|
and has_bottle(world, state, player),
|
||||||
"Beaconator": lambda state: (can_kill_wither(state, player) and has_diamond_pickaxe(state, player) and
|
"Monsters Hunted": lambda state: (can_respawn_ender_dragon(world, state, player)
|
||||||
state.has("Progressive Resource Crafting", player, 2)),
|
and can_kill_ender_dragon(world, state, player)
|
||||||
"Withering Heights": lambda state: can_kill_wither(state, player),
|
and can_kill_wither(world, state, player)
|
||||||
"A Balanced Diet": lambda state: (has_bottle(state, player) and has_gold_ingots(state, player) and # honey bottle; gapple
|
and state.has("Fishing Rod", player)),
|
||||||
state.has("Progressive Resource Crafting", player, 2) and state.can_reach('The End', 'Region', player)), # notch apple, chorus fruit
|
"Enchanter": lambda state: can_enchant(world, state, player),
|
||||||
"Subspace Bubble": lambda state: has_diamond_pickaxe(state, player),
|
"Voluntary Exile": lambda state: basic_combat(world, state, player),
|
||||||
"Country Lode, Take Me Home": lambda state: state.can_reach("Hidden in the Depths", "Location", player) and has_gold_ingots(state, player),
|
"Eye Spy": lambda state: enter_stronghold(world, state, player),
|
||||||
"Bee Our Guest": lambda state: state.has("Campfire", player) and has_bottle(state, player),
|
"Serious Dedication": lambda state: (can_brew_potions(world, state, player)
|
||||||
"Uneasy Alliance": lambda state: has_diamond_pickaxe(state, player) and state.has('Fishing Rod', player),
|
and state.has("Bed", player)
|
||||||
"Diamonds!": lambda state: state.has("Progressive Tools", player, 2) and has_iron_ingots(state, player),
|
and has_diamond_pickaxe(world, state, player)
|
||||||
"A Throwaway Joke": lambda state: can_adventure(state, player),
|
and has_gold_ingots(world, state, player)),
|
||||||
"Sticky Situation": lambda state: state.has("Campfire", player) and has_bottle(state, player),
|
"Postmortal": lambda state: complete_raid(world, state, player),
|
||||||
"Ol' Betsy": lambda state: craft_crossbow(state, player),
|
"Adventuring Time": lambda state: can_adventure(world, state, player),
|
||||||
"Cover Me in Debris": lambda state: (state.has("Progressive Armor", player, 2) and
|
"Hero of the Village": lambda state: complete_raid(world, state, player),
|
||||||
state.has("8 Netherite Scrap", player, 2) and state.has("Progressive Resource Crafting", player) and
|
"Hidden in the Depths": lambda state: can_brew_potions(world, state, player)
|
||||||
has_diamond_pickaxe(state, player) and has_iron_ingots(state, player) and
|
and state.has("Bed", player)
|
||||||
can_brew_potions(state, player) and state.has("Bed", player)),
|
and has_diamond_pickaxe(world, state, player),
|
||||||
|
"Beaconator": lambda state: (can_kill_wither(world, state, player)
|
||||||
|
and has_diamond_pickaxe(world, state, player)
|
||||||
|
and state.has("Progressive Resource Crafting", player, 2)),
|
||||||
|
"Withering Heights": lambda state: can_kill_wither(world, state, player),
|
||||||
|
"A Balanced Diet": lambda state: (has_bottle(world, state, player)
|
||||||
|
and has_gold_ingots(world, state, player)
|
||||||
|
and state.has("Progressive Resource Crafting", player, 2)
|
||||||
|
and state.can_reach_region('The End', player)),
|
||||||
|
# notch apple, chorus fruit
|
||||||
|
"Subspace Bubble": lambda state: has_diamond_pickaxe(world, state, player),
|
||||||
|
"Country Lode, Take Me Home": lambda state: state.can_reach_location("Hidden in the Depths", player)
|
||||||
|
and has_gold_ingots(world, state, player),
|
||||||
|
"Bee Our Guest": lambda state: state.has("Campfire", player)
|
||||||
|
and has_bottle(world, state, player),
|
||||||
|
"Uneasy Alliance": lambda state: has_diamond_pickaxe(world, state, player)
|
||||||
|
and state.has('Fishing Rod', player),
|
||||||
|
"Diamonds!": lambda state: state.has("Progressive Tools", player, 2)
|
||||||
|
and has_iron_ingots(world, state, player),
|
||||||
|
"A Throwaway Joke": lambda state: can_adventure(world, state, player),
|
||||||
|
"Sticky Situation": lambda state: state.has("Campfire", player)
|
||||||
|
and has_bottle(world, state, player),
|
||||||
|
"Ol' Betsy": lambda state: craft_crossbow(world, state, player),
|
||||||
|
"Cover Me in Debris": lambda state: state.has("Progressive Armor", player, 2)
|
||||||
|
and state.has("8 Netherite Scrap", player, 2)
|
||||||
|
and state.has("Progressive Resource Crafting", player)
|
||||||
|
and has_diamond_pickaxe(world, state, player)
|
||||||
|
and has_iron_ingots(world, state, player)
|
||||||
|
and can_brew_potions(world, state, player)
|
||||||
|
and state.has("Bed", player),
|
||||||
"Hot Topic": lambda state: state.has("Progressive Resource Crafting", player),
|
"Hot Topic": lambda state: state.has("Progressive Resource Crafting", player),
|
||||||
"The Lie": lambda state: has_iron_ingots(state, player) and state.has("Bucket", player),
|
"The Lie": lambda state: has_iron_ingots(world, state, player)
|
||||||
"On a Rail": lambda state: has_iron_ingots(state, player) and state.has('Progressive Tools', player, 2),
|
and state.has("Bucket", player),
|
||||||
"When Pigs Fly": lambda state: ((fortress_loot(state, player) or complete_raid(state, player)) and
|
"On a Rail": lambda state: has_iron_ingots(world, state, player)
|
||||||
state.has("Saddle", player) and state.has("Fishing Rod", player) and can_adventure(state, player)),
|
and state.has('Progressive Tools', player, 2),
|
||||||
"Overkill": lambda state: (can_brew_potions(state, player) and
|
"When Pigs Fly": lambda state: (
|
||||||
(state.has("Progressive Weapons", player) or state.can_reach('The Nether', 'Region', player))),
|
fortress_loot(world, state, player)
|
||||||
|
or complete_raid(world, state, player)
|
||||||
|
)
|
||||||
|
and state.has("Saddle", player)
|
||||||
|
and state.has("Fishing Rod", player)
|
||||||
|
and can_adventure(world, state, player),
|
||||||
|
"Overkill": lambda state: can_brew_potions(world, state, player)
|
||||||
|
and (
|
||||||
|
state.has("Progressive Weapons", player)
|
||||||
|
or state.can_reach_region('The Nether', player)
|
||||||
|
),
|
||||||
"Librarian": lambda state: state.has("Enchanting", player),
|
"Librarian": lambda state: state.has("Enchanting", player),
|
||||||
"Overpowered": lambda state: (has_iron_ingots(state, player) and
|
"Overpowered": lambda state: has_iron_ingots(world, state, player)
|
||||||
state.has('Progressive Tools', player, 2) and basic_combat(state, player)),
|
and state.has('Progressive Tools', player, 2)
|
||||||
"Wax On": lambda state: (has_copper_ingots(state, player) and state.has('Campfire', player) and
|
and basic_combat(world, state, player),
|
||||||
state.has('Progressive Resource Crafting', player, 2)),
|
"Wax On": lambda state: has_copper_ingots(world, state, player)
|
||||||
"Wax Off": lambda state: (has_copper_ingots(state, player) and state.has('Campfire', player) and
|
and state.has('Campfire', player)
|
||||||
state.has('Progressive Resource Crafting', player, 2)),
|
and state.has('Progressive Resource Crafting', player, 2),
|
||||||
"The Cutest Predator": lambda state: has_iron_ingots(state, player) and state.has('Bucket', player),
|
"Wax Off": lambda state: has_copper_ingots(world, state, player)
|
||||||
"The Healing Power of Friendship": lambda state: has_iron_ingots(state, player) and state.has('Bucket', player),
|
and state.has('Campfire', player)
|
||||||
"Is It a Bird?": lambda state: has_spyglass(state, player) and can_adventure(state, player),
|
and state.has('Progressive Resource Crafting', player, 2),
|
||||||
"Is It a Balloon?": lambda state: has_spyglass(state, player),
|
"The Cutest Predator": lambda state: has_iron_ingots(world, state, player)
|
||||||
"Is It a Plane?": lambda state: has_spyglass(state, player) and can_respawn_ender_dragon(state, player),
|
and state.has('Bucket', player),
|
||||||
"Surge Protector": lambda state: (state.has("Channeling Book", player) and
|
"The Healing Power of Friendship": lambda state: has_iron_ingots(world, state, player)
|
||||||
can_use_anvil(state, player) and can_enchant(state, player) and overworld_villager(state, player)),
|
and state.has('Bucket', player),
|
||||||
"Light as a Rabbit": lambda state: can_adventure(state, player) and has_iron_ingots(state, player) and state.has('Bucket', player),
|
"Is It a Bird?": lambda state: has_spyglass(world, state, player)
|
||||||
"Glow and Behold!": lambda state: can_adventure(state, player),
|
and can_adventure(world, state, player),
|
||||||
"Whatever Floats Your Goat!": lambda state: can_adventure(state, player),
|
"Is It a Balloon?": lambda state: has_spyglass(world, state, player),
|
||||||
"Caves & Cliffs": lambda state: has_iron_ingots(state, player) and state.has('Bucket', player) and state.has('Progressive Tools', player, 2),
|
"Is It a Plane?": lambda state: has_spyglass(world, state, player)
|
||||||
"Feels like home": lambda state: (has_iron_ingots(state, player) and state.has('Bucket', player) and state.has('Fishing Rod', player) and
|
and can_respawn_ender_dragon(world, state, player),
|
||||||
(fortress_loot(state, player) or complete_raid(state, player)) and state.has("Saddle", player)),
|
"Surge Protector": lambda state: state.has("Channeling Book", player)
|
||||||
"Sound of Music": lambda state: state.has("Progressive Tools", player, 2) and has_iron_ingots(state, player) and basic_combat(state, player),
|
and can_use_anvil(world, state, player)
|
||||||
"Star Trader": lambda state: (has_iron_ingots(state, player) and state.has('Bucket', player) and
|
and can_enchant(world, state, player)
|
||||||
(state.can_reach("The Nether", 'Region', player) or
|
and overworld_villager(world, state, player),
|
||||||
state.can_reach("Nether Fortress", 'Region', player) or # soul sand for water elevator
|
"Light as a Rabbit": lambda state: can_adventure(world, state, player)
|
||||||
can_piglin_trade(state, player)) and
|
and has_iron_ingots(world, state, player)
|
||||||
overworld_villager(state, player)),
|
and state.has('Bucket', player),
|
||||||
"Birthday Song": lambda state: state.can_reach("The Lie", "Location", player) and state.has("Progressive Tools", player, 2) and has_iron_ingots(state, player),
|
"Glow and Behold!": lambda state: can_adventure(world, state, player),
|
||||||
"Bukkit Bukkit": lambda state: state.has("Bucket", player) and has_iron_ingots(state, player) and can_adventure(state, player),
|
"Whatever Floats Your Goat!": lambda state: can_adventure(world, state, player),
|
||||||
"It Spreads": lambda state: can_adventure(state, player) and has_iron_ingots(state, player) and state.has("Progressive Tools", player, 2),
|
"Caves & Cliffs": lambda state: has_iron_ingots(world, state, player)
|
||||||
"Sneak 100": lambda state: can_adventure(state, player) and has_iron_ingots(state, player) and state.has("Progressive Tools", player, 2),
|
and state.has('Bucket', player)
|
||||||
"When the Squad Hops into Town": lambda state: can_adventure(state, player) and state.has("Lead", player),
|
and state.has('Progressive Tools', player, 2),
|
||||||
"With Our Powers Combined!": lambda state: can_adventure(state, player) and state.has("Lead", player),
|
"Feels like home": lambda state: has_iron_ingots(world, state, player)
|
||||||
|
and state.has('Bucket', player)
|
||||||
|
and state.has('Fishing Rod', player)
|
||||||
|
and (
|
||||||
|
fortress_loot(world, state, player)
|
||||||
|
or complete_raid(world, state, player)
|
||||||
|
)
|
||||||
|
and state.has("Saddle", player),
|
||||||
|
"Sound of Music": lambda state: state.has("Progressive Tools", player, 2)
|
||||||
|
and has_iron_ingots(world, state, player)
|
||||||
|
and basic_combat(world, state, player),
|
||||||
|
"Star Trader": lambda state: has_iron_ingots(world, state, player)
|
||||||
|
and state.has('Bucket', player)
|
||||||
|
and (
|
||||||
|
state.can_reach_region("The Nether", player) # soul sand in nether
|
||||||
|
or state.can_reach_region("Nether Fortress", player) # soul sand in fortress if not in nether for water elevator
|
||||||
|
or can_piglin_trade(world, state, player) # piglins give soul sand
|
||||||
|
)
|
||||||
|
and overworld_villager(world, state, player),
|
||||||
|
"Birthday Song": lambda state: state.can_reach_location("The Lie", player)
|
||||||
|
and state.has("Progressive Tools", player, 2)
|
||||||
|
and has_iron_ingots(world, state, player),
|
||||||
|
"Bukkit Bukkit": lambda state: state.has("Bucket", player)
|
||||||
|
and has_iron_ingots(world, state, player)
|
||||||
|
and can_adventure(world, state, player),
|
||||||
|
"It Spreads": lambda state: can_adventure(world, state, player)
|
||||||
|
and has_iron_ingots(world, state, player)
|
||||||
|
and state.has("Progressive Tools", player, 2),
|
||||||
|
"Sneak 100": lambda state: can_adventure(world, state, player)
|
||||||
|
and has_iron_ingots(world, state, player)
|
||||||
|
and state.has("Progressive Tools", player, 2),
|
||||||
|
"When the Squad Hops into Town": lambda state: can_adventure(world, state, player)
|
||||||
|
and state.has("Lead", player),
|
||||||
|
"With Our Powers Combined!": lambda state: can_adventure(world, state, player)
|
||||||
|
and state.has("Lead", player),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rules_lookup
|
return rules_lookup
|
||||||
|
|
||||||
|
|
||||||
def set_rules(mc_world: World) -> None:
|
def set_rules(self: "MinecraftWorld") -> None:
|
||||||
multiworld = mc_world.multiworld
|
multiworld = self.multiworld
|
||||||
player = mc_world.player
|
player = self.player
|
||||||
|
|
||||||
rules_lookup = get_rules_lookup(player)
|
rules_lookup = get_rules_lookup(self, player)
|
||||||
|
|
||||||
# Set entrance rules
|
# Set entrance rules
|
||||||
for entrance_name, rule in rules_lookup["entrances"].items():
|
for entrance_name, rule in rules_lookup["entrances"].items():
|
||||||
|
@ -281,33 +476,33 @@ def set_rules(mc_world: World) -> None:
|
||||||
multiworld.get_location(location_name, player).access_rule = rule
|
multiworld.get_location(location_name, player).access_rule = rule
|
||||||
|
|
||||||
# Set rules surrounding completion
|
# Set rules surrounding completion
|
||||||
bosses = multiworld.required_bosses[player]
|
bosses = self.options.required_bosses
|
||||||
postgame_advancements = set()
|
postgame_advancements = set()
|
||||||
if bosses.dragon:
|
if bosses.dragon:
|
||||||
postgame_advancements.update(Constants.exclusion_info["ender_dragon"])
|
postgame_advancements.update(Constants.exclusion_info["ender_dragon"])
|
||||||
if bosses.wither:
|
if bosses.wither:
|
||||||
postgame_advancements.update(Constants.exclusion_info["wither"])
|
postgame_advancements.update(Constants.exclusion_info["wither"])
|
||||||
|
|
||||||
def location_count(state: CollectionState) -> bool:
|
def location_count(state: CollectionState) -> int:
|
||||||
return len([location for location in multiworld.get_locations(player) if
|
return len([location for location in multiworld.get_locations(player) if
|
||||||
location.address != None and
|
location.address is not None and
|
||||||
location.can_reach(state)])
|
location.can_reach(state)])
|
||||||
|
|
||||||
def defeated_bosses(state: CollectionState) -> bool:
|
def defeated_bosses(state: CollectionState) -> bool:
|
||||||
return ((not bosses.dragon or state.has("Ender Dragon", player))
|
return ((not bosses.dragon or state.has("Ender Dragon", player))
|
||||||
and (not bosses.wither or state.has("Wither", player)))
|
and (not bosses.wither or state.has("Wither", player)))
|
||||||
|
|
||||||
egg_shards = min(multiworld.egg_shards_required[player], multiworld.egg_shards_available[player])
|
egg_shards = min(self.options.egg_shards_required.value, self.options.egg_shards_available.value)
|
||||||
completion_requirements = lambda state: (location_count(state) >= multiworld.advancement_goal[player]
|
completion_requirements = lambda state: (location_count(state) >= self.options.advancement_goal
|
||||||
and state.has("Dragon Egg Shard", player, egg_shards))
|
and state.has("Dragon Egg Shard", player, egg_shards))
|
||||||
multiworld.completion_condition[player] = lambda state: completion_requirements(state) and defeated_bosses(state)
|
multiworld.completion_condition[player] = lambda state: completion_requirements(state) and defeated_bosses(state)
|
||||||
|
|
||||||
# Set exclusions on hard/unreasonable/postgame
|
# Set exclusions on hard/unreasonable/postgame
|
||||||
excluded_advancements = set()
|
excluded_advancements = set()
|
||||||
if not multiworld.include_hard_advancements[player]:
|
if not self.options.include_hard_advancements:
|
||||||
excluded_advancements.update(Constants.exclusion_info["hard"])
|
excluded_advancements.update(Constants.exclusion_info["hard"])
|
||||||
if not multiworld.include_unreasonable_advancements[player]:
|
if not self.options.include_unreasonable_advancements:
|
||||||
excluded_advancements.update(Constants.exclusion_info["unreasonable"])
|
excluded_advancements.update(Constants.exclusion_info["unreasonable"])
|
||||||
if not multiworld.include_postgame_advancements[player]:
|
if not self.options.include_postgame_advancements:
|
||||||
excluded_advancements.update(postgame_advancements)
|
excluded_advancements.update(postgame_advancements)
|
||||||
exclusion_rules(multiworld, player, excluded_advancements)
|
exclusion_rules(multiworld, player, excluded_advancements)
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
from worlds.AutoWorld import World
|
|
||||||
|
|
||||||
from . import Constants
|
from . import Constants
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from . import MinecraftWorld
|
||||||
|
|
||||||
def shuffle_structures(mc_world: World) -> None:
|
|
||||||
multiworld = mc_world.multiworld
|
def shuffle_structures(self: "MinecraftWorld") -> None:
|
||||||
player = mc_world.player
|
multiworld = self.multiworld
|
||||||
|
player = self.player
|
||||||
|
|
||||||
default_connections = Constants.region_info["default_connections"]
|
default_connections = Constants.region_info["default_connections"]
|
||||||
illegal_connections = Constants.region_info["illegal_connections"]
|
illegal_connections = Constants.region_info["illegal_connections"]
|
||||||
|
|
||||||
# Get all unpaired exits and all regions without entrances (except the Menu)
|
# Get all unpaired exits and all regions without entrances (except the Menu)
|
||||||
# This function is destructive on these lists.
|
# This function is destructive on these lists.
|
||||||
exits = [exit.name for r in multiworld.regions if r.player == player for exit in r.exits if exit.connected_region == None]
|
exits = [exit.name for r in multiworld.regions if r.player == player for exit in r.exits if exit.connected_region is None]
|
||||||
structs = [r.name for r in multiworld.regions if r.player == player and r.entrances == [] and r.name != 'Menu']
|
structs = [r.name for r in multiworld.regions if r.player == player and r.entrances == [] and r.name != 'Menu']
|
||||||
exits_spoiler = exits[:] # copy the original order for the spoiler log
|
exits_spoiler = exits[:] # copy the original order for the spoiler log
|
||||||
|
|
||||||
|
@ -26,19 +28,19 @@ def shuffle_structures(mc_world: World) -> None:
|
||||||
raise Exception(f"Invalid connection: {exit} => {struct} for player {player} ({multiworld.player_name[player]})")
|
raise Exception(f"Invalid connection: {exit} => {struct} for player {player} ({multiworld.player_name[player]})")
|
||||||
|
|
||||||
# Connect plando structures first
|
# Connect plando structures first
|
||||||
if multiworld.plando_connections[player]:
|
if self.options.plando_connections:
|
||||||
for conn in multiworld.plando_connections[player]:
|
for conn in self.plando_connections:
|
||||||
set_pair(conn.entrance, conn.exit)
|
set_pair(conn.entrance, conn.exit)
|
||||||
|
|
||||||
# The algorithm tries to place the most restrictive structures first. This algorithm always works on the
|
# The algorithm tries to place the most restrictive structures first. This algorithm always works on the
|
||||||
# relatively small set of restrictions here, but does not work on all possible inputs with valid configurations.
|
# relatively small set of restrictions here, but does not work on all possible inputs with valid configurations.
|
||||||
if multiworld.shuffle_structures[player]:
|
if self.options.shuffle_structures:
|
||||||
structs.sort(reverse=True, key=lambda s: len(illegal_connections.get(s, [])))
|
structs.sort(reverse=True, key=lambda s: len(illegal_connections.get(s, [])))
|
||||||
for struct in structs[:]:
|
for struct in structs[:]:
|
||||||
try:
|
try:
|
||||||
exit = multiworld.random.choice([e for e in exits if e not in illegal_connections.get(struct, [])])
|
exit = self.random.choice([e for e in exits if e not in illegal_connections.get(struct, [])])
|
||||||
except IndexError:
|
except IndexError:
|
||||||
raise Exception(f"No valid structure placements remaining for player {player} ({multiworld.player_name[player]})")
|
raise Exception(f"No valid structure placements remaining for player {player} ({self.player_name})")
|
||||||
set_pair(exit, struct)
|
set_pair(exit, struct)
|
||||||
else: # write remaining default connections
|
else: # write remaining default connections
|
||||||
for (exit, struct) in default_connections:
|
for (exit, struct) in default_connections:
|
||||||
|
@ -49,9 +51,9 @@ def shuffle_structures(mc_world: World) -> None:
|
||||||
try:
|
try:
|
||||||
assert len(exits) == len(structs) == 0
|
assert len(exits) == len(structs) == 0
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
raise Exception(f"Failed to connect all Minecraft structures for player {player} ({multiworld.player_name[player]})")
|
raise Exception(f"Failed to connect all Minecraft structures for player {player} ({self.player_name})")
|
||||||
|
|
||||||
for exit in exits_spoiler:
|
for exit in exits_spoiler:
|
||||||
multiworld.get_entrance(exit, player).connect(multiworld.get_region(pairs[exit], player))
|
multiworld.get_entrance(exit, player).connect(multiworld.get_region(pairs[exit], player))
|
||||||
if multiworld.shuffle_structures[player] or multiworld.plando_connections[player]:
|
if self.options.shuffle_structures or self.options.plando_connections:
|
||||||
multiworld.spoiler.set_entrance(exit, pairs[exit], 'entrance', player)
|
multiworld.spoiler.set_entrance(exit, pairs[exit], 'entrance', player)
|
||||||
|
|
|
@ -9,7 +9,7 @@ from BaseClasses import Region, Entrance, Item, Tutorial, ItemClassification, Lo
|
||||||
from worlds.AutoWorld import World, WebWorld
|
from worlds.AutoWorld import World, WebWorld
|
||||||
|
|
||||||
from . import Constants
|
from . import Constants
|
||||||
from .Options import minecraft_options
|
from .Options import MinecraftOptions
|
||||||
from .Structures import shuffle_structures
|
from .Structures import shuffle_structures
|
||||||
from .ItemPool import build_item_pool, get_junk_item_names
|
from .ItemPool import build_item_pool, get_junk_item_names
|
||||||
from .Rules import set_rules
|
from .Rules import set_rules
|
||||||
|
@ -83,8 +83,9 @@ class MinecraftWorld(World):
|
||||||
structures, and materials to create a portal to another world. Defeat the Ender Dragon, and claim
|
structures, and materials to create a portal to another world. Defeat the Ender Dragon, and claim
|
||||||
victory!
|
victory!
|
||||||
"""
|
"""
|
||||||
game: str = "Minecraft"
|
game = "Minecraft"
|
||||||
option_definitions = minecraft_options
|
options_dataclass = MinecraftOptions
|
||||||
|
options: MinecraftOptions
|
||||||
settings: typing.ClassVar[MinecraftSettings]
|
settings: typing.ClassVar[MinecraftSettings]
|
||||||
topology_present = True
|
topology_present = True
|
||||||
web = MinecraftWebWorld()
|
web = MinecraftWebWorld()
|
||||||
|
@ -95,20 +96,20 @@ class MinecraftWorld(World):
|
||||||
def _get_mc_data(self) -> Dict[str, Any]:
|
def _get_mc_data(self) -> Dict[str, Any]:
|
||||||
exits = [connection[0] for connection in Constants.region_info["default_connections"]]
|
exits = [connection[0] for connection in Constants.region_info["default_connections"]]
|
||||||
return {
|
return {
|
||||||
'world_seed': self.multiworld.per_slot_randoms[self.player].getrandbits(32),
|
'world_seed': self.random.getrandbits(32),
|
||||||
'seed_name': self.multiworld.seed_name,
|
'seed_name': self.multiworld.seed_name,
|
||||||
'player_name': self.multiworld.get_player_name(self.player),
|
'player_name': self.player_name,
|
||||||
'player_id': self.player,
|
'player_id': self.player,
|
||||||
'client_version': client_version,
|
'client_version': client_version,
|
||||||
'structures': {exit: self.multiworld.get_entrance(exit, self.player).connected_region.name for exit in exits},
|
'structures': {exit: self.multiworld.get_entrance(exit, self.player).connected_region.name for exit in exits},
|
||||||
'advancement_goal': self.multiworld.advancement_goal[self.player].value,
|
'advancement_goal': self.options.advancement_goal.value,
|
||||||
'egg_shards_required': min(self.multiworld.egg_shards_required[self.player].value,
|
'egg_shards_required': min(self.options.egg_shards_required.value,
|
||||||
self.multiworld.egg_shards_available[self.player].value),
|
self.options.egg_shards_available.value),
|
||||||
'egg_shards_available': self.multiworld.egg_shards_available[self.player].value,
|
'egg_shards_available': self.options.egg_shards_available.value,
|
||||||
'required_bosses': self.multiworld.required_bosses[self.player].current_key,
|
'required_bosses': self.options.required_bosses.current_key,
|
||||||
'MC35': bool(self.multiworld.send_defeated_mobs[self.player].value),
|
'MC35': bool(self.options.send_defeated_mobs.value),
|
||||||
'death_link': bool(self.multiworld.death_link[self.player].value),
|
'death_link': bool(self.options.death_link.value),
|
||||||
'starting_items': str(self.multiworld.starting_items[self.player].value),
|
'starting_items': json.dumps(self.options.starting_items.value),
|
||||||
'race': self.multiworld.is_race,
|
'race': self.multiworld.is_race,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +130,7 @@ class MinecraftWorld(World):
|
||||||
loc.place_locked_item(self.create_event_item(event_name))
|
loc.place_locked_item(self.create_event_item(event_name))
|
||||||
region.locations.append(loc)
|
region.locations.append(loc)
|
||||||
|
|
||||||
def create_event_item(self, name: str) -> None:
|
def create_event_item(self, name: str) -> Item:
|
||||||
item = self.create_item(name)
|
item = self.create_item(name)
|
||||||
item.classification = ItemClassification.progression
|
item.classification = ItemClassification.progression
|
||||||
return item
|
return item
|
||||||
|
@ -176,15 +177,10 @@ class MinecraftWorld(World):
|
||||||
f.write(b64encode(bytes(json.dumps(data), 'utf-8')))
|
f.write(b64encode(bytes(json.dumps(data), 'utf-8')))
|
||||||
|
|
||||||
def fill_slot_data(self) -> dict:
|
def fill_slot_data(self) -> dict:
|
||||||
slot_data = self._get_mc_data()
|
return self._get_mc_data()
|
||||||
for option_name in minecraft_options:
|
|
||||||
option = getattr(self.multiworld, option_name)[self.player]
|
|
||||||
if slot_data.get(option_name, None) is None and type(option.value) in {str, int}:
|
|
||||||
slot_data[option_name] = int(option.value)
|
|
||||||
return slot_data
|
|
||||||
|
|
||||||
def get_filler_item_name(self) -> str:
|
def get_filler_item_name(self) -> str:
|
||||||
return get_junk_item_names(self.multiworld.random, 1)[0]
|
return get_junk_item_names(self.random, 1)[0]
|
||||||
|
|
||||||
|
|
||||||
class MinecraftLocation(Location):
|
class MinecraftLocation(Location):
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
from . import MCTestBase
|
from . import MCTestBase
|
||||||
from ..Constants import region_info
|
from ..Constants import region_info
|
||||||
from ..Options import minecraft_options
|
from .. import Options
|
||||||
|
|
||||||
from BaseClasses import ItemClassification
|
from BaseClasses import ItemClassification
|
||||||
|
|
||||||
class AdvancementTestBase(MCTestBase):
|
class AdvancementTestBase(MCTestBase):
|
||||||
options = {
|
options = {
|
||||||
"advancement_goal": minecraft_options["advancement_goal"].range_end
|
"advancement_goal": Options.AdvancementGoal.range_end
|
||||||
}
|
}
|
||||||
# beatability test implicit
|
# beatability test implicit
|
||||||
|
|
||||||
class ShardTestBase(MCTestBase):
|
class ShardTestBase(MCTestBase):
|
||||||
options = {
|
options = {
|
||||||
"egg_shards_required": minecraft_options["egg_shards_required"].range_end,
|
"egg_shards_required": Options.EggShardsRequired.range_end,
|
||||||
"egg_shards_available": minecraft_options["egg_shards_available"].range_end
|
"egg_shards_available": Options.EggShardsAvailable.range_end
|
||||||
}
|
}
|
||||||
|
|
||||||
# check that itempool is not overfilled with shards
|
# check that itempool is not overfilled with shards
|
||||||
|
@ -29,7 +29,7 @@ class CompassTestBase(MCTestBase):
|
||||||
|
|
||||||
class NoBeeTestBase(MCTestBase):
|
class NoBeeTestBase(MCTestBase):
|
||||||
options = {
|
options = {
|
||||||
"bee_traps": 0
|
"bee_traps": Options.BeeTraps.range_start
|
||||||
}
|
}
|
||||||
|
|
||||||
# With no bees, there are no traps in the pool
|
# With no bees, there are no traps in the pool
|
||||||
|
@ -40,7 +40,7 @@ class NoBeeTestBase(MCTestBase):
|
||||||
|
|
||||||
class AllBeeTestBase(MCTestBase):
|
class AllBeeTestBase(MCTestBase):
|
||||||
options = {
|
options = {
|
||||||
"bee_traps": 100
|
"bee_traps": Options.BeeTraps.range_end
|
||||||
}
|
}
|
||||||
|
|
||||||
# With max bees, there are no filler items, only bee traps
|
# With max bees, there are no filler items, only bee traps
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from test.TestBase import TestBase, WorldTestBase
|
from test.bases import TestBase, WorldTestBase
|
||||||
from .. import MinecraftWorld
|
from .. import MinecraftWorld, MinecraftOptions
|
||||||
|
|
||||||
|
|
||||||
class MCTestBase(WorldTestBase, TestBase):
|
class MCTestBase(WorldTestBase, TestBase):
|
||||||
|
|
Loading…
Reference in New Issue