Move Factorio, Hollow Knight and Minecraft Options into AutoWorld

This commit is contained in:
Fabian Dill 2021-06-25 23:32:13 +02:00
parent cc85edafc4
commit 7f8bb10fc5
17 changed files with 338 additions and 289 deletions

View File

@ -147,6 +147,9 @@ class MultiWorld():
for option_set in Options.option_sets:
for option in option_set:
setattr(self, option, getattr(args, option, {}))
for world in AutoWorld.AutoWorldRegister.world_types.values():
for option in world.options:
setattr(self, option, getattr(args, option, {}))
for player in self.player_ids:
self.custom_data[player] = {}
self.worlds[player] = AutoWorld.AutoWorldRegister.world_types[self.game[player]](self, player)
@ -1501,22 +1504,14 @@ class Spoiler(object):
outfile.write('Progression Balanced: %s\n' % (
'Yes' if self.metadata['progression_balancing'][player] else 'No'))
outfile.write('Accessibility: %s\n' % self.metadata['accessibility'][player])
if player in self.world.hk_player_ids:
for hk_option in Options.hollow_knight_options:
res = getattr(self.world, hk_option)[player]
outfile.write(f'{hk_option+":":33}{res}\n')
elif player in self.world.factorio_player_ids:
for f_option in Options.factorio_options:
options = self.world.worlds[player].options
if options:
for f_option in options:
res = getattr(self.world, f_option)[player]
outfile.write(f'{f_option+":":33}{bool_to_text(res) if type(res) == Options.Toggle else res.get_option_name()}\n')
elif player in self.world.minecraft_player_ids:
for mc_option in Options.minecraft_options:
res = getattr(self.world, mc_option)[player]
outfile.write(f'{mc_option+":":33}{bool_to_text(res) if type(res) == Options.Toggle else res.get_option_name()}\n')
elif player in self.world.alttp_player_ids:
if player in self.world.alttp_player_ids:
for team in range(self.world.teams):
outfile.write('%s%s\n' % (
f"Hash - {self.world.player_names[player][team]} (Team {team + 1}): " if

View File

@ -519,10 +519,9 @@ def main(args, seed=None):
if player not in world.alttp_player_ids:
connect_names[name] = (i, player)
if world.hk_player_ids:
import Options
for slot in world.hk_player_ids:
slots_data = slot_data[slot] = {}
for option_name in Options.hollow_knight_options:
for option_name in world.worlds[slot].options:
option = getattr(world, option_name)[slot]
slots_data[option_name] = int(option.value)
for slot in world.minecraft_player_ids:

View File

@ -548,35 +548,27 @@ def roll_settings(weights: dict, plando_options: typing.Set[str] = frozenset(("b
if ret.game == "A Link to the Past":
roll_alttp_settings(ret, game_weights, plando_options)
elif ret.game == "Hollow Knight":
for option_name, option in Options.hollow_knight_options.items():
setattr(ret, option_name, option.from_any(get_choice(option_name, game_weights)))
elif ret.game == "Factorio":
for option_name, option in Options.factorio_options.items():
elif ret.game in AutoWorldRegister.world_types:
for option_name, option in AutoWorldRegister.world_types[ret.game].options.items():
if option_name in game_weights:
if issubclass(option, Options.OptionDict): # get_choice should probably land in the Option class
if issubclass(option, Options.OptionDict):
setattr(ret, option_name, option.from_any(game_weights[option_name]))
else:
setattr(ret, option_name, option.from_any(get_choice(option_name, game_weights)))
else:
setattr(ret, option_name, option(option.default))
elif ret.game == "Minecraft":
for option_name, option in Options.minecraft_options.items():
if option_name in game_weights:
setattr(ret, option_name, option.from_any(get_choice(option_name, game_weights)))
else:
setattr(ret, option_name, option(option.default))
# bad hardcoded behavior to make this work for now
ret.plando_connections = []
if "connections" in plando_options:
options = game_weights.get("plando_connections", [])
for placement in options:
if roll_percentage(get_choice("percentage", placement, 100)):
ret.plando_connections.append(PlandoConnection(
get_choice("entrance", placement),
get_choice("exit", placement),
get_choice("direction", placement, "both")
))
if ret.game == "Minecraft":
# bad hardcoded behavior to make this work for now
ret.plando_connections = []
if "connections" in plando_options:
options = game_weights.get("plando_connections", [])
for placement in options:
if roll_percentage(get_choice("percentage", placement, 100)):
ret.plando_connections.append(PlandoConnection(
get_choice("entrance", placement),
get_choice("exit", placement),
get_choice("direction", placement, "both")
))
else:
raise Exception(f"Unsupported game {ret.game}")
return ret

View File

@ -296,157 +296,12 @@ alttp_options: typing.Dict[str, type(Option)] = {
"shop_item_slots": ShopItemSlots,
}
hollow_knight_randomize_options: typing.Dict[str, type(Option)] = {
"RandomizeDreamers": DefaultOnToggle,
"RandomizeSkills": DefaultOnToggle,
"RandomizeCharms": DefaultOnToggle,
"RandomizeKeys": DefaultOnToggle,
"RandomizeGeoChests": Toggle,
"RandomizeMaskShards": DefaultOnToggle,
"RandomizeVesselFragments": DefaultOnToggle,
"RandomizeCharmNotches": Toggle,
"RandomizePaleOre": DefaultOnToggle,
"RandomizeRancidEggs": Toggle,
"RandomizeRelics": DefaultOnToggle,
"RandomizeMaps": Toggle,
"RandomizeStags": Toggle,
"RandomizeGrubs": Toggle,
"RandomizeWhisperingRoots": Toggle,
"RandomizeRocks": Toggle,
"RandomizeSoulTotems": Toggle,
"RandomizePalaceTotems": Toggle,
"RandomizeLoreTablets": Toggle,
"RandomizeLifebloodCocoons": Toggle,
"RandomizeFlames": Toggle
}
hollow_knight_skip_options: typing.Dict[str, type(Option)] = {
"MILDSKIPS": Toggle,
"SPICYSKIPS": Toggle,
"FIREBALLSKIPS": Toggle,
"ACIDSKIPS": Toggle,
"SPIKETUNNELS": Toggle,
"DARKROOMS": Toggle,
"CURSED": Toggle,
"SHADESKIPS": Toggle,
}
hollow_knight_options: typing.Dict[str, type(Option)] = {**hollow_knight_randomize_options,
**hollow_knight_skip_options}
class MaxSciencePack(Choice):
option_automation_science_pack = 0
option_logistic_science_pack = 1
option_military_science_pack = 2
option_chemical_science_pack = 3
option_production_science_pack = 4
option_utility_science_pack = 5
option_space_science_pack = 6
default = 6
def get_allowed_packs(self):
return {option.replace("_", "-") for option, value in self.options.items() if value <= self.value} - \
{"space-science-pack"} # with rocket launch being the goal, post-launch techs don't make sense
class TechCost(Choice):
option_very_easy = 0
option_easy = 1
option_kind = 2
option_normal = 3
option_hard = 4
option_very_hard = 5
option_insane = 6
default = 3
class FreeSamples(Choice):
option_none = 0
option_single_craft = 1
option_half_stack = 2
option_stack = 3
default = 3
class TechTreeLayout(Choice):
option_single = 0
option_small_diamonds = 1
option_medium_diamonds = 2
option_large_diamonds = 3
option_small_pyramids = 4
option_medium_pyramids = 5
option_large_pyramids = 6
option_small_funnels = 7
option_medium_funnels = 8
option_large_funnels = 9
option_funnels = 4
alias_pyramid = 6
alias_funnel = 9
default = 0
class TechTreeInformation(Choice):
option_none = 0
option_advancement = 1
option_full = 2
default = 2
class RecipeTime(Choice):
option_vanilla = 0
option_fast = 1
option_normal = 2
option_slow = 4
option_chaos = 5
class FactorioStartItems(OptionDict):
default = {"burner-mining-drill": 19, "stone-furnace": 19}
factorio_options: typing.Dict[str, type(Option)] = {
"max_science_pack": MaxSciencePack,
"tech_tree_layout": TechTreeLayout,
"tech_cost": TechCost,
"free_samples": FreeSamples,
"tech_tree_information": TechTreeInformation,
"starting_items": FactorioStartItems,
"recipe_time": RecipeTime,
"imported_blueprints": DefaultOnToggle,
}
class AdvancementGoal(Choice):
option_few = 0
option_normal = 1
option_many = 2
default = 1
class CombatDifficulty(Choice):
option_easy = 0
option_normal = 1
option_hard = 2
default = 1
minecraft_options: typing.Dict[str, type(Option)] = {
"advancement_goal": AdvancementGoal,
"combat_difficulty": CombatDifficulty,
"include_hard_advancements": Toggle,
"include_insane_advancements": Toggle,
"include_postgame_advancements": Toggle,
"shuffle_structures": Toggle
}
# replace with World.options
option_sets = (
minecraft_options,
factorio_options,
# minecraft_options,
# factorio_options,
alttp_options,
hollow_knight_options
# hollow_knight_options
)
if __name__ == "__main__":

View File

@ -1,3 +1,4 @@
import worlds.hk.Options
from BaseClasses import MultiWorld
from worlds.hk.Regions import create_regions
from worlds.hk import gen_hollow
@ -9,10 +10,9 @@ class TestVanilla(TestBase):
def setUp(self):
self.world = MultiWorld(1)
self.world.game[1] = "Hollow Knight"
import Options
for hk_option in Options.hollow_knight_randomize_options:
for hk_option in worlds.hk.Options.hollow_knight_randomize_options:
setattr(self.world, hk_option, {1: True})
for hk_option, option in Options.hollow_knight_skip_options.items():
for hk_option, option in worlds.hk.Options.hollow_knight_skip_options.items():
setattr(self.world, hk_option, {1: option.default})
create_regions(self.world, 1)
gen_hollow(self.world, 1)

View File

@ -1,3 +1,4 @@
import worlds.minecraft.Options
from test.TestBase import TestBase
from BaseClasses import MultiWorld
from worlds.minecraft import minecraft_gen_item_pool
@ -31,9 +32,9 @@ class TestMinecraft(TestBase):
exclusion_pools = ['hard', 'insane', 'postgame']
for pool in exclusion_pools:
setattr(self.world, f"include_{pool}_advancements", [False, False])
setattr(self.world, "advancement_goal", [0, Options.AdvancementGoal(value=0)])
setattr(self.world, "advancement_goal", [0, worlds.minecraft.Options.AdvancementGoal(value=0)])
setattr(self.world, "shuffle_structures", [False, False])
setattr(self.world, "combat_difficulty", [0, Options.CombatDifficulty(value=1)])
setattr(self.world, "combat_difficulty", [0, worlds.minecraft.Options.CombatDifficulty(value=1)])
minecraft_create_regions(self.world, 1)
link_minecraft_structures(self.world, 1)
minecraft_gen_item_pool(self.world, 1)

View File

@ -27,6 +27,7 @@ class World(metaclass=AutoWorldRegister):
world: MultiWorld
player: int
options: dict = {}
def __init__(self, world: MultiWorld, player: int):
self.world = world

View File

@ -751,18 +751,11 @@ bonk_addresses = [0x4CF6C, 0x4CFBA, 0x4CFE0, 0x4CFFB, 0x4D018, 0x4D01B, 0x4D028,
0x4D3F8, 0x4D416, 0x4D420, 0x4D423, 0x4D42D, 0x4D449, 0x4D48C, 0x4D4D9, 0x4D4DC, 0x4D4E3,
0x4D504, 0x4D507, 0x4D55E, 0x4D56A]
def get_nonnative_item_sprite(game: str) -> int:
def get_nonnative_item_sprite(item: str) -> int:
return 0x6B # set all non-native sprites to Power Star as per 13 to 2 vote at
# https://discord.com/channels/731205301247803413/827141303330406408/852102450822905886
# def get_nonnative_item_sprite(game):
# game_to_id = {
# "Factorio": 0x09, # Hammer
# "Hollow Knight": 0x21, # Bug Catching Net
# "Minecraft": 0x13, # Shovel
# }
# return game_to_id.get(game, 0x6B) # default to Power Star
def patch_rom(world, rom, player, team, enemized):
local_random = world.slot_seeds[player]
@ -1724,20 +1717,7 @@ def write_custom_shops(rom, world, player):
if item is None:
break
if not item['item'] in item_table: # item not native to ALTTP
# This is a terrible way to do this, please fix later
from worlds.hk.Items import lookup_id_to_name as hk_lookup
from worlds.factorio.Technologies import lookup_id_to_name as factorio_lookup
from worlds.minecraft.Items import lookup_id_to_name as mc_lookup
item_name = item['item']
if item_name in hk_lookup.values():
item_game = 'Hollow Knight'
elif item_name in factorio_lookup.values():
item_game = 'Factorio'
elif item_name in mc_lookup.values():
item_game = 'Minecraft'
else:
item_game = 'Generic'
item_code = get_nonnative_item_sprite(item_game)
item_code = get_nonnative_item_sprite(item['item'])
else:
item_code = ItemFactory(item['item'], player).code
if item['item'] == 'Single Arrow' and item['player'] == 0 and world.retro[player]:

View File

@ -9,7 +9,7 @@ import json
import jinja2
import Utils
import shutil
import Options
from . import Options
from BaseClasses import MultiWorld
from .Technologies import tech_table, rocket_recipes, recipes, free_sample_blacklist

View File

@ -0,0 +1,85 @@
import typing
from Options import Choice, OptionDict, Option, DefaultOnToggle
class MaxSciencePack(Choice):
option_automation_science_pack = 0
option_logistic_science_pack = 1
option_military_science_pack = 2
option_chemical_science_pack = 3
option_production_science_pack = 4
option_utility_science_pack = 5
option_space_science_pack = 6
default = 6
def get_allowed_packs(self):
return {option.replace("_", "-") for option, value in self.options.items() if value <= self.value} - \
{"space-science-pack"} # with rocket launch being the goal, post-launch techs don't make sense
class TechCost(Choice):
option_very_easy = 0
option_easy = 1
option_kind = 2
option_normal = 3
option_hard = 4
option_very_hard = 5
option_insane = 6
default = 3
class FreeSamples(Choice):
option_none = 0
option_single_craft = 1
option_half_stack = 2
option_stack = 3
default = 3
class TechTreeLayout(Choice):
option_single = 0
option_small_diamonds = 1
option_medium_diamonds = 2
option_large_diamonds = 3
option_small_pyramids = 4
option_medium_pyramids = 5
option_large_pyramids = 6
option_small_funnels = 7
option_medium_funnels = 8
option_large_funnels = 9
option_funnels = 4
alias_pyramid = 6
alias_funnel = 9
default = 0
class TechTreeInformation(Choice):
option_none = 0
option_advancement = 1
option_full = 2
default = 2
class RecipeTime(Choice):
option_vanilla = 0
option_fast = 1
option_normal = 2
option_slow = 4
option_chaos = 5
class FactorioStartItems(OptionDict):
default = {"burner-mining-drill": 19, "stone-furnace": 19}
factorio_options: typing.Dict[str, type(Option)] = {
"max_science_pack": MaxSciencePack,
"tech_tree_layout": TechTreeLayout,
"tech_cost": TechCost,
"free_samples": FreeSamples,
"tech_tree_information": TechTreeInformation,
"starting_items": FactorioStartItems,
"recipe_time": RecipeTime,
"imported_blueprints": DefaultOnToggle,
}

View File

@ -1,7 +1,6 @@
from typing import Dict, List, Set
from BaseClasses import MultiWorld
from Options import TechTreeLayout
from worlds.factorio.Options import TechTreeLayout
funnel_layers = {TechTreeLayout.option_small_funnels: 3,
TechTreeLayout.option_medium_funnels: 4,

View File

@ -4,11 +4,12 @@ from typing import Dict, Set, FrozenSet
import os
import json
import Options
import Utils
import logging
import functools
from . import Options
factorio_id = 2 ** 17
source_folder = Utils.local_path("data", "factorio")

View File

@ -5,7 +5,7 @@ from .Technologies import tech_table, recipe_sources, technology_table, advancem
all_ingredient_names, required_technologies, get_rocket_requirements, rocket_recipes
from .Shapes import get_shapes
from .Mod import generate_mod
from .Options import factorio_options
class Factorio(World):
game: str = "Factorio"
@ -80,6 +80,8 @@ class Factorio(World):
world.completion_condition[player] = lambda state: state.has('Victory', player)
options = factorio_options
def set_custom_technologies(world: MultiWorld, player: int):
custom_technologies = {}
allowed_packs = world.max_science_pack[player].get_allowed_packs()

39
worlds/hk/Options.py Normal file
View File

@ -0,0 +1,39 @@
import typing
from Options import Option, DefaultOnToggle, Toggle
hollow_knight_randomize_options: typing.Dict[str, type(Option)] = {
"RandomizeDreamers": DefaultOnToggle,
"RandomizeSkills": DefaultOnToggle,
"RandomizeCharms": DefaultOnToggle,
"RandomizeKeys": DefaultOnToggle,
"RandomizeGeoChests": Toggle,
"RandomizeMaskShards": DefaultOnToggle,
"RandomizeVesselFragments": DefaultOnToggle,
"RandomizeCharmNotches": Toggle,
"RandomizePaleOre": DefaultOnToggle,
"RandomizeRancidEggs": Toggle,
"RandomizeRelics": DefaultOnToggle,
"RandomizeMaps": Toggle,
"RandomizeStags": Toggle,
"RandomizeGrubs": Toggle,
"RandomizeWhisperingRoots": Toggle,
"RandomizeRocks": Toggle,
"RandomizeSoulTotems": Toggle,
"RandomizePalaceTotems": Toggle,
"RandomizeLoreTablets": Toggle,
"RandomizeLifebloodCocoons": Toggle,
"RandomizeFlames": Toggle
}
hollow_knight_skip_options: typing.Dict[str, type(Option)] = {
"MILDSKIPS": Toggle,
"SPICYSKIPS": Toggle,
"FIREBALLSKIPS": Toggle,
"ACIDSKIPS": Toggle,
"SPIKETUNNELS": Toggle,
"DARKROOMS": Toggle,
"CURSED": Toggle,
"SHADESKIPS": Toggle,
}
hollow_knight_options: typing.Dict[str, type(Option)] = {**hollow_knight_randomize_options,
**hollow_knight_skip_options}

View File

@ -0,0 +1,27 @@
import typing
from Options import Choice, Option, Toggle
class AdvancementGoal(Choice):
option_few = 0
option_normal = 1
option_many = 2
default = 1
class CombatDifficulty(Choice):
option_easy = 0
option_normal = 1
option_hard = 2
default = 1
minecraft_options: typing.Dict[str, type(Option)] = {
"advancement_goal": AdvancementGoal,
"combat_difficulty": CombatDifficulty,
"include_hard_advancements": Toggle,
"include_insane_advancements": Toggle,
"include_postgame_advancements": Toggle,
"shuffle_structures": Toggle
}

View File

@ -1,17 +1,16 @@
from ..generic.Rules import set_rule
from .Locations import exclusion_table, events_table
from BaseClasses import Region, Entrance, Location, MultiWorld, Item
from Options import AdvancementGoal
from BaseClasses import MultiWorld
def set_rules(world: MultiWorld, player: int):
def reachable_locations(state):
postgame_advancements = set(exclusion_table['postgame'].keys())
postgame_advancements.add('Free the End')
for event in events_table.keys():
postgame_advancements.add(event)
return [location for location in world.get_locations() if
(player is None or location.player == player) and
return [location for location in world.get_locations() if
(player is None or location.player == player) and
(location.name not in postgame_advancements) and
location.can_reach(state)]
@ -19,18 +18,22 @@ def set_rules(world: MultiWorld, player: int):
goal_map = {
'few': 30,
'normal': 50,
'many': 70
'many': 70
}
goal = goal_map[getattr(world, 'advancement_goal')[player].get_option_name()]
can_complete = lambda state: len(reachable_locations(state)) >= goal and state.can_reach('The End', 'Region', player) and state.can_kill_ender_dragon(player)
can_complete = lambda state: len(reachable_locations(state)) >= goal and state.can_reach('The End', 'Region',
player) and state.can_kill_ender_dragon(
player)
if world.logic[player] != 'nologic':
if world.logic[player] != 'nologic':
world.completion_condition[player] = lambda state: state.has('Victory', player)
set_rule(world.get_entrance("Nether Portal", player), lambda state: state.has('Flint and Steel', player) and
(state.has('Bucket', player) or state.has('Progressive Tools', player, 3)) and
set_rule(world.get_entrance("Nether Portal", player), lambda state: state.has('Flint and Steel', player) and
(state.has('Bucket', player) or state.has(
'Progressive Tools', player, 3)) and
state.has_iron_ingots(player))
set_rule(world.get_entrance("End Portal", player), lambda state: state.enter_stronghold(player) and state.has('3 Ender Pearls', player, 4))
set_rule(world.get_entrance("End Portal", player),
lambda state: state.enter_stronghold(player) and state.has('3 Ender Pearls', player, 4))
set_rule(world.get_entrance("Overworld Structure 1", player), lambda state: state.can_adventure(player))
set_rule(world.get_entrance("Overworld Structure 2", player), lambda state: state.can_adventure(player))
set_rule(world.get_entrance("Nether Structure 1", player), lambda state: state.can_adventure(player))
@ -41,108 +44,178 @@ def set_rules(world: MultiWorld, player: int):
set_rule(world.get_location("Who is Cutting Onions?", player), lambda state: state.can_piglin_trade(player))
set_rule(world.get_location("Oh Shiny", player), lambda state: state.can_piglin_trade(player))
set_rule(world.get_location("Suit Up", player), lambda state: state.has("Progressive Armor", player) and state.has_iron_ingots(player))
set_rule(world.get_location("Very Very Frightening", player), lambda state: state.has("Channeling Book", player) and state.can_use_anvil(player) and state.can_enchant(player) and \
((world.get_region('Village', player).entrances[0].parent_region.name != 'The End' and state.can_reach('Village', 'Region', player)) or state.can_reach('Zombie Doctor', 'Location', player))) # need villager into the overworld for lightning strike
set_rule(world.get_location("Hot Stuff", player), lambda state: state.has("Bucket", player) and state.has_iron_ingots(player))
set_rule(world.get_location("Free the End", player), lambda state: can_complete(state) and state.has('Ingot Crafting', player) and state.can_reach('The Nether', 'Region', player))
set_rule(world.get_location("A Furious Cocktail", player), lambda state: state.can_brew_potions(player) and
state.has("Fishing Rod", player) and # Water Breathing
state.can_reach('The Nether', 'Region', player) and # Regeneration, Fire Resistance, gold nuggets
state.can_reach('Village', 'Region', player) and # Night Vision, Invisibility
state.can_reach('Bring Home the Beacon', 'Location', player)) # Resistance
set_rule(world.get_location("Suit Up", player),
lambda state: state.has("Progressive Armor", player) and state.has_iron_ingots(player))
set_rule(world.get_location("Very Very Frightening", player),
lambda state: state.has("Channeling Book", player) and state.can_use_anvil(player) and state.can_enchant(
player) and \
((world.get_region('Village', player).entrances[
0].parent_region.name != 'The End' and state.can_reach('Village', 'Region',
player)) or state.can_reach(
'Zombie Doctor', 'Location',
player))) # need villager into the overworld for lightning strike
set_rule(world.get_location("Hot Stuff", player),
lambda state: state.has("Bucket", player) and state.has_iron_ingots(player))
set_rule(world.get_location("Free the End", player),
lambda state: can_complete(state) and state.has('Ingot Crafting', player) and state.can_reach('The Nether',
'Region',
player))
set_rule(world.get_location("A Furious Cocktail", player), lambda state: state.can_brew_potions(player) and
state.has("Fishing Rod",
player) and # Water Breathing
state.can_reach('The Nether', 'Region',
player) and # Regeneration, Fire Resistance, gold nuggets
state.can_reach('Village', 'Region',
player) and # Night Vision, Invisibility
state.can_reach('Bring Home the Beacon',
'Location',
player)) # Resistance
set_rule(world.get_location("Best Friends Forever", player), lambda state: True)
set_rule(world.get_location("Bring Home the Beacon", player), lambda state: state.can_kill_wither(player) and state.has_diamond_pickaxe(player) and
state.has("Ingot Crafting", player) and state.has("Resource Blocks", player))
set_rule(world.get_location("Not Today, Thank You", player), lambda state: state.has("Shield", player) and state.has_iron_ingots(player))
set_rule(world.get_location("Isn't It Iron Pick", player), lambda state: state.has("Progressive Tools", player, 2) and state.has_iron_ingots(player))
set_rule(world.get_location("Bring Home the Beacon", player),
lambda state: state.can_kill_wither(player) and state.has_diamond_pickaxe(player) and
state.has("Ingot Crafting", player) and state.has("Resource Blocks", player))
set_rule(world.get_location("Not Today, Thank You", player),
lambda state: state.has("Shield", player) and state.has_iron_ingots(player))
set_rule(world.get_location("Isn't It Iron Pick", player),
lambda state: state.has("Progressive Tools", player, 2) and state.has_iron_ingots(player))
set_rule(world.get_location("Local Brewery", player), lambda state: state.can_brew_potions(player))
set_rule(world.get_location("The Next Generation", player), lambda state: can_complete(state))
set_rule(world.get_location("Fishy Business", player), lambda state: state.has("Fishing Rod", player))
set_rule(world.get_location("Hot Tourist Destinations", player), lambda state: True)
set_rule(world.get_location("This Boat Has Legs", player), lambda state: (state.fortress_loot(player) or state.complete_raid(player)) and state.has("Fishing Rod", player))
set_rule(world.get_location("This Boat Has Legs", player),
lambda state: (state.fortress_loot(player) or state.complete_raid(player)) and state.has("Fishing Rod",
player))
set_rule(world.get_location("Sniper Duel", player), lambda state: state.has("Archery", player))
set_rule(world.get_location("Nether", player), lambda state: True)
set_rule(world.get_location("Great View From Up Here", player), lambda state: state.basic_combat(player))
set_rule(world.get_location("How Did We Get Here?", player), lambda state: state.can_brew_potions(player) and state.has_gold_ingots(player) and # most effects; Absorption
state.can_reach('End City', 'Region', player) and state.can_reach('The Nether', 'Region', player) and # Levitation; potion ingredients
state.has("Fishing Rod", player) and state.has("Archery", player) and # Pufferfish, Nautilus Shells; spectral arrows
state.can_reach("Bring Home the Beacon", "Location", player) and # Haste
state.can_reach("Hero of the Village", "Location", player)) # Bad Omen, Hero of the Village
set_rule(world.get_location("Bullseye", player), lambda state: state.has("Archery", player) and state.has("Progressive Tools", player, 2) and state.has_iron_ingots(player))
set_rule(world.get_location("How Did We Get Here?", player),
lambda state: state.can_brew_potions(player) and state.has_gold_ingots(
player) and # most effects; Absorption
state.can_reach('End City', 'Region', player) and state.can_reach('The Nether', 'Region',
player) and # Levitation; potion ingredients
state.has("Fishing Rod", player) and state.has("Archery",
player) and # Pufferfish, Nautilus Shells; spectral arrows
state.can_reach("Bring Home the Beacon", "Location", player) and # Haste
state.can_reach("Hero of the Village", "Location", player)) # Bad Omen, Hero of the Village
set_rule(world.get_location("Bullseye", player),
lambda state: state.has("Archery", player) and state.has("Progressive Tools", player,
2) and state.has_iron_ingots(player))
set_rule(world.get_location("Spooky Scary Skeleton", player), lambda state: state.basic_combat(player))
set_rule(world.get_location("Two by Two", player), lambda state: state.has_iron_ingots(player) and state.can_adventure(player)) # shears > seagrass > turtles; nether > striders; gold carrots > horses skips ingots
set_rule(world.get_location("Two by Two", player),
lambda state: state.has_iron_ingots(player) and state.can_adventure(
player)) # shears > seagrass > turtles; nether > striders; gold carrots > horses skips ingots
set_rule(world.get_location("Stone Age", player), lambda state: True)
set_rule(world.get_location("Two Birds, One Arrow", player), lambda state: state.craft_crossbow(player) and state.can_enchant(player))
set_rule(world.get_location("Two Birds, One Arrow", player),
lambda state: state.craft_crossbow(player) and state.can_enchant(player))
set_rule(world.get_location("We Need to Go Deeper", player), lambda state: True)
set_rule(world.get_location("Who's the Pillager Now?", player), lambda state: state.craft_crossbow(player))
set_rule(world.get_location("Getting an Upgrade", player), lambda state: state.has("Progressive Tools", player))
set_rule(world.get_location("Tactical Fishing", player), lambda state: state.has("Bucket", player) and state.has_iron_ingots(player))
set_rule(world.get_location("Zombie Doctor", player), lambda state: state.can_brew_potions(player) and state.has_gold_ingots(player))
set_rule(world.get_location("Tactical Fishing", player),
lambda state: state.has("Bucket", player) and state.has_iron_ingots(player))
set_rule(world.get_location("Zombie Doctor", player),
lambda state: state.can_brew_potions(player) and state.has_gold_ingots(player))
set_rule(world.get_location("The City at the End of the Game", player), lambda state: True)
set_rule(world.get_location("Ice Bucket Challenge", player), lambda state: state.has_diamond_pickaxe(player))
set_rule(world.get_location("Remote Getaway", player), lambda state: True)
set_rule(world.get_location("Into Fire", player), lambda state: state.basic_combat(player))
set_rule(world.get_location("War Pigs", player), lambda state: state.basic_combat(player))
set_rule(world.get_location("Take Aim", player), lambda state: state.has("Archery", player))
set_rule(world.get_location("Total Beelocation", player), lambda state: state.has("Silk Touch Book", player) and state.can_use_anvil(player) and state.can_enchant(player))
set_rule(world.get_location("Arbalistic", player), lambda state: state.craft_crossbow(player) and state.has("Piercing IV Book", player) and
state.can_use_anvil(player) and state.can_enchant(player))
set_rule(world.get_location("The End... Again...", player), lambda state: can_complete(state) and state.has("Ingot Crafting", player) and state.can_reach('The Nether', 'Region', player)) # furnace for glass, nether for ghast tears
set_rule(world.get_location("Total Beelocation", player),
lambda state: state.has("Silk Touch Book", player) and state.can_use_anvil(player) and state.can_enchant(
player))
set_rule(world.get_location("Arbalistic", player),
lambda state: state.craft_crossbow(player) and state.has("Piercing IV Book", player) and
state.can_use_anvil(player) and state.can_enchant(player))
set_rule(world.get_location("The End... Again...", player),
lambda state: can_complete(state) and state.has("Ingot Crafting", player) and state.can_reach('The Nether',
'Region',
player)) # furnace for glass, nether for ghast tears
set_rule(world.get_location("Acquire Hardware", player), lambda state: state.has_iron_ingots(player))
set_rule(world.get_location("Not Quite \"Nine\" Lives", player), lambda state: state.can_piglin_trade(player) and state.has("Resource Blocks", player))
set_rule(world.get_location("Cover Me With Diamonds", player), lambda state: state.has("Progressive Armor", player, 2) and state.can_reach("Diamonds!", "Location", player))
set_rule(world.get_location("Not Quite \"Nine\" Lives", player),
lambda state: state.can_piglin_trade(player) and state.has("Resource Blocks", player))
set_rule(world.get_location("Cover Me With Diamonds", player),
lambda state: state.has("Progressive Armor", player, 2) and state.can_reach("Diamonds!", "Location",
player))
set_rule(world.get_location("Sky's the Limit", player), lambda state: state.basic_combat(player))
set_rule(world.get_location("Hired Help", player), lambda state: state.has("Resource Blocks", player) and state.has_iron_ingots(player))
set_rule(world.get_location("Hired Help", player),
lambda state: state.has("Resource Blocks", player) and state.has_iron_ingots(player))
set_rule(world.get_location("Return to Sender", player), lambda state: True)
set_rule(world.get_location("Sweet Dreams", player), lambda state: state.has("Bed", player) or state.can_reach('Village', 'Region', player))
set_rule(world.get_location("You Need a Mint", player), lambda state: can_complete(state) and state.has_bottle_mc(player))
set_rule(world.get_location("Sweet Dreams", player),
lambda state: state.has("Bed", player) or state.can_reach('Village', 'Region', player))
set_rule(world.get_location("You Need a Mint", player),
lambda state: can_complete(state) and state.has_bottle_mc(player))
set_rule(world.get_location("Adventure", player), lambda state: True)
set_rule(world.get_location("Monsters Hunted", player), lambda state: can_complete(state) and state.can_kill_wither(player) and state.has("Fishing Rod", player)) # pufferfish for Water Breathing
set_rule(world.get_location("Monsters Hunted", player),
lambda state: can_complete(state) and state.can_kill_wither(player) and state.has("Fishing Rod",
player)) # pufferfish for Water Breathing
set_rule(world.get_location("Enchanter", player), lambda state: state.can_enchant(player))
set_rule(world.get_location("Voluntary Exile", player), lambda state: state.basic_combat(player))
set_rule(world.get_location("Eye Spy", player), lambda state: state.enter_stronghold(player))
set_rule(world.get_location("The End", player), lambda state: True)
set_rule(world.get_location("Serious Dedication", player), lambda state: state.can_reach("Hidden in the Depths", "Location", player) and state.has_gold_ingots(player))
set_rule(world.get_location("Serious Dedication", player),
lambda state: state.can_reach("Hidden in the Depths", "Location", player) and state.has_gold_ingots(
player))
set_rule(world.get_location("Postmortal", player), lambda state: state.complete_raid(player))
set_rule(world.get_location("Monster Hunter", player), lambda state: True)
set_rule(world.get_location("Adventuring Time", player), lambda state: state.can_adventure(player))
set_rule(world.get_location("A Seedy Place", player), lambda state: True)
set_rule(world.get_location("Those Were the Days", player), lambda state: True)
set_rule(world.get_location("Hero of the Village", player), lambda state: state.complete_raid(player))
set_rule(world.get_location("Hidden in the Depths", player), lambda state: state.can_brew_potions(player) and state.has("Bed", player) and state.has_diamond_pickaxe(player)) # bed mining :)
set_rule(world.get_location("Beaconator", player), lambda state: state.can_kill_wither(player) and state.has_diamond_pickaxe(player) and
state.has("Ingot Crafting", player) and state.has("Resource Blocks", player))
set_rule(world.get_location("Hidden in the Depths", player),
lambda state: state.can_brew_potions(player) and state.has("Bed", player) and state.has_diamond_pickaxe(
player)) # bed mining :)
set_rule(world.get_location("Beaconator", player),
lambda state: state.can_kill_wither(player) and state.has_diamond_pickaxe(player) and
state.has("Ingot Crafting", player) and state.has("Resource Blocks", player))
set_rule(world.get_location("Withering Heights", player), lambda state: state.can_kill_wither(player))
set_rule(world.get_location("A Balanced Diet", player), lambda state: state.has_bottle_mc(player) and state.has_gold_ingots(player) and # honey bottle; gapple
state.has("Resource Blocks", player) and state.can_reach('The End', 'Region', player)) # notch apple, chorus fruit
set_rule(world.get_location("A Balanced Diet", player),
lambda state: state.has_bottle_mc(player) and state.has_gold_ingots(player) and # honey bottle; gapple
state.has("Resource Blocks", player) and state.can_reach('The End', 'Region',
player)) # notch apple, chorus fruit
set_rule(world.get_location("Subspace Bubble", player), lambda state: state.has_diamond_pickaxe(player))
set_rule(world.get_location("Husbandry", player), lambda state: True)
set_rule(world.get_location("Country Lode, Take Me Home", player), lambda state: state.can_reach("Hidden in the Depths", "Location", player) and state.has_gold_ingots(player))
set_rule(world.get_location("Bee Our Guest", player), lambda state: state.has("Campfire", player) and state.has_bottle_mc(player))
set_rule(world.get_location("Country Lode, Take Me Home", player),
lambda state: state.can_reach("Hidden in the Depths", "Location", player) and state.has_gold_ingots(
player))
set_rule(world.get_location("Bee Our Guest", player),
lambda state: state.has("Campfire", player) and state.has_bottle_mc(player))
set_rule(world.get_location("What a Deal!", player), lambda state: True)
set_rule(world.get_location("Uneasy Alliance", player), lambda state: state.has_diamond_pickaxe(player) and state.has('Fishing Rod', player))
set_rule(world.get_location("Diamonds!", player), lambda state: state.has("Progressive Tools", player, 2) and state.has_iron_ingots(player))
set_rule(world.get_location("A Terrible Fortress", player), lambda state: True) # since you don't have to fight anything
set_rule(world.get_location("A Throwaway Joke", player), lambda state: True) # kill drowned
set_rule(world.get_location("Uneasy Alliance", player),
lambda state: state.has_diamond_pickaxe(player) and state.has('Fishing Rod', player))
set_rule(world.get_location("Diamonds!", player),
lambda state: state.has("Progressive Tools", player, 2) and state.has_iron_ingots(player))
set_rule(world.get_location("A Terrible Fortress", player),
lambda state: True) # since you don't have to fight anything
set_rule(world.get_location("A Throwaway Joke", player), lambda state: True) # kill drowned
set_rule(world.get_location("Minecraft", player), lambda state: True)
set_rule(world.get_location("Sticky Situation", player), lambda state: state.has("Campfire", player) and state.has_bottle_mc(player))
set_rule(world.get_location("Sticky Situation", player),
lambda state: state.has("Campfire", player) and state.has_bottle_mc(player))
set_rule(world.get_location("Ol' Betsy", player), lambda state: state.craft_crossbow(player))
set_rule(world.get_location("Cover Me in Debris", player), lambda state: state.has("Progressive Armor", player, 2) and
state.has("8 Netherite Scrap", player, 2) and state.has("Ingot Crafting", player) and
state.can_reach("Diamonds!", "Location", player) and state.can_reach("Hidden in the Depths", "Location", player))
set_rule(world.get_location("Cover Me in Debris", player),
lambda state: state.has("Progressive Armor", player, 2) and
state.has("8 Netherite Scrap", player, 2) and state.has("Ingot Crafting", player) and
state.can_reach("Diamonds!", "Location", player) and state.can_reach("Hidden in the Depths",
"Location", player))
set_rule(world.get_location("The End?", player), lambda state: True)
set_rule(world.get_location("The Parrots and the Bats", player), lambda state: True)
set_rule(world.get_location("A Complete Catalogue", player), lambda state: True) # kill fish for raw
set_rule(world.get_location("A Complete Catalogue", player), lambda state: True) # kill fish for raw
set_rule(world.get_location("Getting Wood", player), lambda state: True)
set_rule(world.get_location("Time to Mine!", player), lambda state: True)
set_rule(world.get_location("Hot Topic", player), lambda state: state.has("Ingot Crafting", player))
set_rule(world.get_location("Bake Bread", player), lambda state: True)
set_rule(world.get_location("The Lie", player), lambda state: state.has_iron_ingots(player) and state.has("Bucket", player))
set_rule(world.get_location("On a Rail", player), lambda state: state.has_iron_ingots(player) and state.has('Progressive Tools', player, 2)) # powered rails
set_rule(world.get_location("The Lie", player),
lambda state: state.has_iron_ingots(player) and state.has("Bucket", player))
set_rule(world.get_location("On a Rail", player),
lambda state: state.has_iron_ingots(player) and state.has('Progressive Tools', player, 2)) # powered rails
set_rule(world.get_location("Time to Strike!", player), lambda state: True)
set_rule(world.get_location("Cow Tipper", player), lambda state: True)
set_rule(world.get_location("When Pigs Fly", player), lambda state: (state.fortress_loot(player) or state.complete_raid(player)) and state.has("Fishing Rod", player) and state.can_adventure(player))
set_rule(world.get_location("Overkill", player), lambda state: state.can_brew_potions(player) and (state.has("Progressive Weapons", player) or state.can_reach('The Nether', 'Region', player))) # strength 1 + stone axe crit OR strength 2 + wood axe crit
set_rule(world.get_location("When Pigs Fly", player),
lambda state: (state.fortress_loot(player) or state.complete_raid(player)) and state.has("Fishing Rod",
player) and state.can_adventure(
player))
set_rule(world.get_location("Overkill", player), lambda state: state.can_brew_potions(player) and (
state.has("Progressive Weapons", player) or state.can_reach('The Nether', 'Region',
player))) # strength 1 + stone axe crit OR strength 2 + wood axe crit
set_rule(world.get_location("Librarian", player), lambda state: state.has("Enchanting", player))
set_rule(world.get_location("Overpowered", player), lambda state: state.has("Resource Blocks", player) and state.has_gold_ingots(player))
set_rule(world.get_location("Overpowered", player),
lambda state: state.has("Resource Blocks", player) and state.has_gold_ingots(player))

View File

@ -1,16 +1,16 @@
from random import Random
from .Items import MinecraftItem, item_table, item_frequencies
from .Locations import exclusion_table, events_table
from .Regions import link_minecraft_structures
from .Rules import set_rules
from BaseClasses import MultiWorld
from Options import minecraft_options
from .Options import minecraft_options
from ..AutoWorld import World
class MinecraftWorld(World):
game: str = "Minecraft"
options = minecraft_options
client_version = (0, 3)