From c55983af5fb8de2cc9e43058f0b2d973a2b0ab4d Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sun, 9 May 2021 17:46:26 +0200 Subject: [PATCH] Factorio: add starting_items --- Mystery.py | 5 ++- Options.py | 47 +++++++++++++++++++++++--- data/factorio/mod_template/control.lua | 12 ++++--- playerSettings.yaml | 3 ++ worlds/factorio/Mod.py | 3 +- 5 files changed, 60 insertions(+), 10 deletions(-) diff --git a/Mystery.py b/Mystery.py index c4ca1f03..8be7c1b0 100644 --- a/Mystery.py +++ b/Mystery.py @@ -536,7 +536,10 @@ def roll_settings(weights: dict, plando_options: typing.Set[str] = frozenset(("b elif ret.game == "Factorio": for option_name, option in Options.factorio_options.items(): if option_name in weights: - setattr(ret, option_name, option.from_any(get_choice(option_name, weights))) + if issubclass(option, Options.OptionDict): # get_choice should probably land in the Option class + setattr(ret, option_name, option.from_any(weights[option_name])) + else: + setattr(ret, option_name, option.from_any(get_choice(option_name, weights))) else: setattr(ret, option_name, option(option.default)) elif ret.game == "Minecraft": diff --git a/Options.py b/Options.py index e9c2e80e..820c6089 100644 --- a/Options.py +++ b/Options.py @@ -103,12 +103,43 @@ class Choice(Option): f'known options are {", ".join(f"{option}" for option in cls.name_lookup.values())}') @classmethod - def from_any(cls, data: typing.Any): + def from_any(cls, data: typing.Any) -> Choice: if type(data) == int and data in cls.options.values(): return cls(data) return cls.from_text(str(data)) +class OptionNameSet(Option): + default = frozenset() + + def __init__(self, value: typing.Set[str]): + self.value: typing.Set[str] = value + + @classmethod + def from_text(cls, text: str) -> OptionNameSet: + return cls({option.strip() for option in text.split(",")}) + + @classmethod + def from_any(cls, data: typing.Any) -> OptionNameSet: + if type(data) == set: + return cls(data) + return cls.from_text(str(data)) + + +class OptionDict(Option): + default = {} + + def __init__(self, value: typing.Dict[str, typing.Any]): + self.value: typing.Dict[str, typing.Any] = value + + @classmethod + def from_any(cls, data: typing.Dict[str, typing.Any]) -> OptionDict: + if type(data) == dict: + return cls(data) + else: + raise NotImplementedError(f"Cannot Convert from non-dictionary, got {type(data)}") + + class Logic(Choice): option_no_glitches = 0 option_minor_glitches = 1 @@ -289,12 +320,18 @@ class Visibility(Choice): default = 1 +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, "visibility": Visibility, - "random_tech_ingredients": Toggle} + "random_tech_ingredients": Toggle, + "starting_items": FactorioStartItems} + class AdvancementGoal(Choice): option_few = 0 @@ -302,14 +339,16 @@ class AdvancementGoal(Choice): option_many = 2 default = 1 -class CombatDifficulty(Choice): + +class CombatDifficulty(Choice): option_easy = 0 option_normal = 1 option_hard = 2 default = 1 + minecraft_options: typing.Dict[str, type(Option)] = { - "advancement_goal": AdvancementGoal, + "advancement_goal": AdvancementGoal, "combat_difficulty": CombatDifficulty, "include_hard_advancements": Toggle, "include_insane_advancements": Toggle, diff --git a/data/factorio/mod_template/control.lua b/data/factorio/mod_template/control.lua index 9fdeaf49..aa765c48 100644 --- a/data/factorio/mod_template/control.lua +++ b/data/factorio/mod_template/control.lua @@ -1,3 +1,10 @@ +{% macro dict_to_lua(dict) -%} +{ + {% for key, value in dict.items() %} + ["{{ key }}"] = {{ value | safe }}{% if not loop.last %},{% endif %} + {% endfor %} +} +{%- endmacro %} require "lib" require "util" @@ -11,10 +18,7 @@ function on_force_created(event) game.forces[event.force].research_queue_enabled = true local data = {} if FREE_SAMPLES ~= 0 then - data['earned_samples'] = { - ["burner-mining-drill"] = 19, - ["stone-furnace"] = 19 - } + data['earned_samples'] = {{ dict_to_lua(starting_items) }} end data["victory"] = 0 global.forcedata[event.force] = data diff --git a/playerSettings.yaml b/playerSettings.yaml index 0efc65e2..8dff638d 100644 --- a/playerSettings.yaml +++ b/playerSettings.yaml @@ -70,6 +70,9 @@ visibility: random_tech_ingredients: on: 1 off: 0 +starting_items: + burner-mining-drill: 19 + stone-furnace: 19 # Minecraft options: advancement_goal: # Number of advancements required (out of 92 total) to spawn the Ender Dragon and complete the game. few: 0 # 30 advancements diff --git a/worlds/factorio/Mod.py b/worlds/factorio/Mod.py index af34705d..1558d24a 100644 --- a/worlds/factorio/Mod.py +++ b/worlds/factorio/Mod.py @@ -71,7 +71,8 @@ def generate_mod(world: MultiWorld, player: int, seedname: str): "tech_cost_scale": tech_cost, "custom_data": world.custom_data[player], "tech_tree_layout_prerequisites": world.tech_tree_layout_prerequisites[player], "rocket_recipe" : rocket_recipes[world.max_science_pack[player].value], - "slot_name": world.player_names[player][0]} + "slot_name": world.player_names[player][0], + "starting_items": world.starting_items[player]} for factorio_option in Options.factorio_options: template_data[factorio_option] = getattr(world, factorio_option)[player].value control_code = control_template.render(**template_data)