diff --git a/worlds/factorio/Mod.py b/worlds/factorio/Mod.py index d4fea3f3a2..5a81dc2b1c 100644 --- a/worlds/factorio/Mod.py +++ b/worlds/factorio/Mod.py @@ -6,6 +6,8 @@ import shutil import threading import zipfile from typing import Optional, TYPE_CHECKING, Any, List, Callable, Tuple, Union +from dataclasses import fields +import datetime import jinja2 @@ -148,10 +150,10 @@ def generate_mod(world: "Factorio", output_directory: str): "goal": options.goal.value, "energy_link": options.energy_link.value, "useless_technologies": useless_technologies, - "chunk_shuffle": options.chunk_shuffle.value if hasattr(options, "chunk_shuffle") else 0, + "chunk_shuffle": options.chunk_shuffle.value if datetime.datetime.today().month == 4 else 0, } - for factorio_option in Options.factorio_options: + for factorio_option in [field.name for field in fields(Options.FactorioOptions)]: if factorio_option in ["free_sample_blacklist", "free_sample_whitelist"]: continue template_data[factorio_option] = getattr(options, factorio_option).value diff --git a/worlds/factorio/Options.py b/worlds/factorio/Options.py index b72d57ad9b..daf422b693 100644 --- a/worlds/factorio/Options.py +++ b/worlds/factorio/Options.py @@ -1,10 +1,10 @@ from __future__ import annotations import typing -import datetime from Options import Choice, OptionDict, OptionSet, Option, DefaultOnToggle, Range, DeathLink, Toggle, \ - StartInventoryPool + StartInventoryPool, PerGameCommonOptions from schema import Schema, Optional, And, Or +from dataclasses import dataclass # schema helpers FloatRange = lambda low, high: And(Or(int, float), lambda f: low <= f <= high) @@ -422,50 +422,44 @@ class EnergyLink(Toggle): display_name = "EnergyLink" -factorio_options: typing.Dict[str, type(Option)] = { - "max_science_pack": MaxSciencePack, - "goal": Goal, - "tech_tree_layout": TechTreeLayout, - "min_tech_cost": MinTechCost, - "max_tech_cost": MaxTechCost, - "tech_cost_distribution": TechCostDistribution, - "tech_cost_mix": TechCostMix, - "ramping_tech_costs": RampingTechCosts, - "silo": Silo, - "satellite": Satellite, - "free_samples": FreeSamples, - "tech_tree_information": TechTreeInformation, - "starting_items": FactorioStartItems, - "free_sample_blacklist": FactorioFreeSampleBlacklist, - "free_sample_whitelist": FactorioFreeSampleWhitelist, - "recipe_time": RecipeTime, - "recipe_ingredients": RecipeIngredients, - "recipe_ingredients_offset": RecipeIngredientsOffset, - "imported_blueprints": ImportedBlueprint, - "world_gen": FactorioWorldGen, - "progressive": Progressive, - "teleport_traps": TeleportTrapCount, - "grenade_traps": GrenadeTrapCount, - "cluster_grenade_traps": ClusterGrenadeTrapCount, - "artillery_traps": ArtilleryTrapCount, - "atomic_rocket_traps": AtomicRocketTrapCount, - "attack_traps": AttackTrapCount, - "evolution_traps": EvolutionTrapCount, - "evolution_trap_increase": EvolutionTrapIncrease, - "death_link": DeathLink, - "energy_link": EnergyLink, - "start_inventory_from_pool": StartInventoryPool, -} - -# spoilers below. If you spoil it for yourself, please at least don't spoil it for anyone else. -if datetime.datetime.today().month == 4: - - class ChunkShuffle(Toggle): - """Entrance Randomizer.""" - display_name = "Chunk Shuffle" +class ChunkShuffle(Toggle): + """Entrance Randomizer. + 2023 April Fool's option. Shuffles chunk border transitions. + Only valid during the Month of April. Forced off otherwise.""" - if datetime.datetime.today().day > 1: - ChunkShuffle.__doc__ += """ - 2023 April Fool's option. Shuffles chunk border transitions.""" - factorio_options["chunk_shuffle"] = ChunkShuffle +@dataclass +class FactorioOptions(PerGameCommonOptions): + max_science_pack: MaxSciencePack + goal: Goal + tech_tree_layout: TechTreeLayout + min_tech_cost: MinTechCost + max_tech_cost: MaxTechCost + tech_cost_distribution: TechCostDistribution + tech_cost_mix: TechCostMix + ramping_tech_costs: RampingTechCosts + silo: Silo + satellite: Satellite + free_samples: FreeSamples + tech_tree_information: TechTreeInformation + starting_items: FactorioStartItems + free_sample_blacklist: FactorioFreeSampleBlacklist + free_sample_whitelist: FactorioFreeSampleWhitelist + recipe_time: RecipeTime + recipe_ingredients: RecipeIngredients + recipe_ingredients_offset: RecipeIngredientsOffset + imported_blueprints: ImportedBlueprint + world_gen: FactorioWorldGen + progressive: Progressive + teleport_traps: TeleportTrapCount + grenade_traps: GrenadeTrapCount + cluster_grenade_traps: ClusterGrenadeTrapCount + artillery_traps: ArtilleryTrapCount + atomic_rocket_traps: AtomicRocketTrapCount + attack_traps: AttackTrapCount + evolution_traps: EvolutionTrapCount + evolution_trap_increase: EvolutionTrapIncrease + death_link: DeathLink + energy_link: EnergyLink + start_inventory_from_pool: StartInventoryPool + chunk_shuffle: ChunkShuffle diff --git a/worlds/factorio/__init__.py b/worlds/factorio/__init__.py index a703fd390e..1073fe9994 100644 --- a/worlds/factorio/__init__.py +++ b/worlds/factorio/__init__.py @@ -11,7 +11,7 @@ from worlds.LauncherComponents import Component, components, Type, launch_subpro from worlds.generic import Rules from .Locations import location_pools, location_table from .Mod import generate_mod -from .Options import factorio_options, MaxSciencePack, Silo, Satellite, TechTreeInformation, Goal, TechCostDistribution, TechCostMix +from .Options import FactorioOptions, MaxSciencePack, Silo, Satellite, TechTreeInformation, Goal, TechCostDistribution, TechCostMix from .Shapes import get_shapes from .Technologies import base_tech_table, recipe_sources, base_technology_table, \ all_ingredient_names, all_product_sources, required_technologies, get_rocket_requirements, \ @@ -88,6 +88,9 @@ class Factorio(World): location_pool: typing.List[FactorioScienceLocation] advancement_technologies: typing.Set[str] + options = FactorioOptions + options_dataclass = FactorioOptions + web = FactorioWeb() item_name_to_id = all_items @@ -308,8 +311,6 @@ class Factorio(World): return super(Factorio, self).collect_item(state, item, remove) - option_definitions = factorio_options - @classmethod def stage_write_spoiler(cls, world, spoiler_handle): factorio_players = world.get_game_players(cls.game)