Factorio: add small_diamonds tech tree layout
This commit is contained in:
parent
e11016b0a2
commit
0586b24579
|
@ -60,6 +60,7 @@ class MultiWorld():
|
||||||
for player in range(1, players + 1):
|
for player in range(1, players + 1):
|
||||||
def set_player_attr(attr, val):
|
def set_player_attr(attr, val):
|
||||||
self.__dict__.setdefault(attr, {})[player] = val
|
self.__dict__.setdefault(attr, {})[player] = val
|
||||||
|
set_player_attr('tech_tree_layout_prerequisites', {})
|
||||||
set_player_attr('_region_cache', {})
|
set_player_attr('_region_cache', {})
|
||||||
set_player_attr('shuffle', "vanilla")
|
set_player_attr('shuffle', "vanilla")
|
||||||
set_player_attr('logic', "noglitches")
|
set_player_attr('logic', "noglitches")
|
||||||
|
|
|
@ -273,6 +273,7 @@ class FreeSamples(Choice):
|
||||||
|
|
||||||
class TechTreeLayout(Choice):
|
class TechTreeLayout(Choice):
|
||||||
option_single = 0
|
option_single = 0
|
||||||
|
option_small_diamonds = 1
|
||||||
default = 0
|
default = 0
|
||||||
|
|
||||||
class Visibility(Choice):
|
class Visibility(Choice):
|
||||||
|
|
|
@ -44,9 +44,14 @@ new_tree_copy.icon_size = table.deepcopy(technologies["{{ item_name }}"].icon_si
|
||||||
new_tree_copy.icon = "__{{ mod_name }}__/graphics/icons/ap.png"
|
new_tree_copy.icon = "__{{ mod_name }}__/graphics/icons/ap.png"
|
||||||
new_tree_copy.icons = nil
|
new_tree_copy.icons = nil
|
||||||
new_tree_copy.icon_size = 512
|
new_tree_copy.icon_size = 512
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{#- add new technology to game #}
|
{#- connect Technology #}
|
||||||
|
{%- if original_tech_name in tech_tree_layout_prerequisites %}
|
||||||
|
{%- for prerequesite in tech_tree_layout_prerequisites[original_tech_name] %}
|
||||||
|
table.insert(new_tree_copy.prerequisites, "ap-{{ tech_table[prerequesite] }}-")
|
||||||
|
{% endfor %}
|
||||||
|
{% endif -%}
|
||||||
|
{#- add new Technology to game #}
|
||||||
data:extend{new_tree_copy}
|
data:extend{new_tree_copy}
|
||||||
|
|
||||||
{% endfor %}
|
{% endfor %}
|
|
@ -38,6 +38,7 @@ progression_balancing:
|
||||||
# Factorio options:
|
# Factorio options:
|
||||||
tech_tree_layout:
|
tech_tree_layout:
|
||||||
single: 1
|
single: 1
|
||||||
|
small_diamonds: 1
|
||||||
max_science_pack:
|
max_science_pack:
|
||||||
automation_science_pack: 0
|
automation_science_pack: 0
|
||||||
logistic_science_pack: 0
|
logistic_science_pack: 0
|
||||||
|
|
|
@ -8,28 +8,27 @@ __all__ = {"lookup_any_item_id_to_name",
|
||||||
from .alttp.Items import lookup_id_to_name as alttp
|
from .alttp.Items import lookup_id_to_name as alttp
|
||||||
from .hk.Items import lookup_id_to_name as hk
|
from .hk.Items import lookup_id_to_name as hk
|
||||||
from .factorio import Technologies
|
from .factorio import Technologies
|
||||||
|
|
||||||
lookup_any_item_id_to_name = {**alttp, **hk, **Technologies.lookup_id_to_name}
|
lookup_any_item_id_to_name = {**alttp, **hk, **Technologies.lookup_id_to_name}
|
||||||
assert len(alttp) + len(hk) + len(Technologies.lookup_id_to_name) == len(lookup_any_item_id_to_name)
|
assert len(alttp) + len(hk) + len(Technologies.lookup_id_to_name) == len(lookup_any_item_id_to_name)
|
||||||
lookup_any_item_name_to_id = {name: id for id, name in lookup_any_item_id_to_name.items()}
|
lookup_any_item_name_to_id = {name: id for id, name in lookup_any_item_id_to_name.items()}
|
||||||
|
|
||||||
|
|
||||||
from .alttp import Regions
|
from .alttp import Regions
|
||||||
from .hk import Locations
|
from .hk import Locations
|
||||||
|
|
||||||
lookup_any_location_id_to_name = {**Regions.lookup_id_to_name, **Locations.lookup_id_to_name,
|
lookup_any_location_id_to_name = {**Regions.lookup_id_to_name, **Locations.lookup_id_to_name,
|
||||||
**Technologies.lookup_id_to_name}
|
**Technologies.lookup_id_to_name}
|
||||||
assert len(Regions.lookup_id_to_name) + len(Locations.lookup_id_to_name) + len(Technologies.lookup_id_to_name) == \
|
assert len(Regions.lookup_id_to_name) + len(Locations.lookup_id_to_name) + len(Technologies.lookup_id_to_name) == \
|
||||||
len(lookup_any_location_id_to_name)
|
len(lookup_any_location_id_to_name)
|
||||||
lookup_any_location_name_to_id = {name: id for id, name in lookup_any_location_id_to_name.items()}
|
lookup_any_location_name_to_id = {name: id for id, name in lookup_any_location_id_to_name.items()}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
network_data_package = {"lookup_any_location_id_to_name": lookup_any_location_id_to_name,
|
network_data_package = {"lookup_any_location_id_to_name": lookup_any_location_id_to_name,
|
||||||
"lookup_any_item_id_to_name": lookup_any_item_id_to_name,
|
"lookup_any_item_id_to_name": lookup_any_item_id_to_name,
|
||||||
"version": 3}
|
"version": 4}
|
||||||
|
|
||||||
|
|
||||||
@enum.unique
|
@enum.unique
|
||||||
class Games(str, enum.Enum):
|
class Games(str, enum.Enum):
|
||||||
HK = "Hollow Knight"
|
HK = "Hollow Knight"
|
||||||
LTTP = "A Link to the Past"
|
LTTP = "A Link to the Past"
|
||||||
Factorio = "Factorio"
|
Factorio = "Factorio"
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,8 @@ def generate_mod(world: MultiWorld, player: int):
|
||||||
6: 10}[world.tech_cost[player].value]
|
6: 10}[world.tech_cost[player].value]
|
||||||
template_data = {"locations": locations, "player_names" : player_names, "tech_table": tech_table,
|
template_data = {"locations": locations, "player_names" : player_names, "tech_table": tech_table,
|
||||||
"mod_name": mod_name, "allowed_science_packs": world.max_science_pack[player].get_allowed_packs(),
|
"mod_name": mod_name, "allowed_science_packs": world.max_science_pack[player].get_allowed_packs(),
|
||||||
"tech_cost_scale": tech_cost}
|
"tech_cost_scale": tech_cost,
|
||||||
|
"tech_tree_layout_prerequisites": world.tech_tree_layout_prerequisites[player]}
|
||||||
for factorio_option in Options.factorio_options:
|
for factorio_option in Options.factorio_options:
|
||||||
template_data[factorio_option] = getattr(world, factorio_option)[player].value
|
template_data[factorio_option] = getattr(world, factorio_option)[player].value
|
||||||
control_code = control_template.render(**template_data)
|
control_code = control_template.render(**template_data)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from __future__ import annotations
|
||||||
# Factorio technologies are imported from a .json document in /data
|
# Factorio technologies are imported from a .json document in /data
|
||||||
from typing import Dict, Set, FrozenSet
|
from typing import Dict, Set, FrozenSet
|
||||||
import json
|
import json
|
||||||
|
@ -16,6 +17,7 @@ technology_table = {}
|
||||||
|
|
||||||
always = lambda state: True
|
always = lambda state: True
|
||||||
|
|
||||||
|
|
||||||
class Technology(): # maybe make subclass of Location?
|
class Technology(): # maybe make subclass of Location?
|
||||||
def __init__(self, name, ingredients):
|
def __init__(self, name, ingredients):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -42,6 +44,14 @@ class Technology(): # maybe make subclass of Location?
|
||||||
|
|
||||||
return always
|
return always
|
||||||
|
|
||||||
|
def get_prior_technologies(self, allowed_packs) -> Set[Technology]:
|
||||||
|
"""Get Technologies that have to precede this one to resolve tree connections."""
|
||||||
|
technologies = set()
|
||||||
|
for ingredient in self.ingredients:
|
||||||
|
if ingredient in allowed_packs:
|
||||||
|
technologies |= required_technologies[ingredient] # technologies that unlock the recipes
|
||||||
|
return technologies
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return self.factorio_id
|
return self.factorio_id
|
||||||
|
|
||||||
|
@ -68,11 +78,7 @@ class Recipe():
|
||||||
# recipes and technologies can share names in Factorio
|
# recipes and technologies can share names in Factorio
|
||||||
for technology_name in sorted(raw):
|
for technology_name in sorted(raw):
|
||||||
data = raw[technology_name]
|
data = raw[technology_name]
|
||||||
|
|
||||||
factorio_id += 1
|
factorio_id += 1
|
||||||
# not used yet
|
|
||||||
# if data["requires"]:
|
|
||||||
# requirements[technology] = set(data["requires"])
|
|
||||||
current_ingredients = set(data["ingredients"])
|
current_ingredients = set(data["ingredients"])
|
||||||
technology = Technology(technology_name, current_ingredients)
|
technology = Technology(technology_name, current_ingredients)
|
||||||
tech_table[technology_name] = technology.factorio_id
|
tech_table[technology_name] = technology.factorio_id
|
||||||
|
@ -87,7 +93,6 @@ for technology, data in raw.items():
|
||||||
del (raw)
|
del (raw)
|
||||||
lookup_id_to_name: Dict[int, str] = {item_id: item_name for item_name, item_id in tech_table.items()}
|
lookup_id_to_name: Dict[int, str] = {item_id: item_name for item_name, item_id in tech_table.items()}
|
||||||
|
|
||||||
all_recipes: Dict[str, Recipe] = {}
|
|
||||||
all_product_sources: Dict[str, Recipe] = {}
|
all_product_sources: Dict[str, Recipe] = {}
|
||||||
for recipe_name, recipe_data in raw_recipes.items():
|
for recipe_name, recipe_data in raw_recipes.items():
|
||||||
# example:
|
# example:
|
||||||
|
@ -95,7 +100,6 @@ for recipe_name, recipe_data in raw_recipes.items():
|
||||||
|
|
||||||
recipe = Recipe(recipe_name, recipe_data["category"], set(recipe_data["ingredients"]), set(recipe_data["products"]))
|
recipe = Recipe(recipe_name, recipe_data["category"], set(recipe_data["ingredients"]), set(recipe_data["products"]))
|
||||||
if recipe.products != recipe.ingredients: # prevents loop recipes like uranium centrifuging
|
if recipe.products != recipe.ingredients: # prevents loop recipes like uranium centrifuging
|
||||||
all_recipes[recipe_name] = recipe
|
|
||||||
for product_name in recipe.products:
|
for product_name in recipe.products:
|
||||||
all_product_sources[product_name] = recipe
|
all_product_sources[product_name] = recipe
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import logging
|
import logging
|
||||||
|
from typing import List, Dict
|
||||||
|
|
||||||
from BaseClasses import Region, Entrance, Location, MultiWorld, Item
|
from BaseClasses import Region, Entrance, Location, MultiWorld, Item
|
||||||
|
from Options import TechTreeLayout
|
||||||
from .Technologies import tech_table, recipe_sources, technology_table, advancement_technologies, required_technologies
|
from .Technologies import tech_table, recipe_sources, technology_table, advancement_technologies, required_technologies
|
||||||
|
|
||||||
static_nodes = {"automation", "logistics"}
|
static_nodes = {"automation", "logistics"}
|
||||||
|
@ -35,7 +36,26 @@ def factorio_create_regions(world: MultiWorld, player: int):
|
||||||
world.regions += [menu, nauvis]
|
world.regions += [menu, nauvis]
|
||||||
|
|
||||||
|
|
||||||
|
def get_shapes(world: MultiWorld, player: int) -> Dict[str, List[str]]:
|
||||||
|
prerequisites = {}
|
||||||
|
if world.tech_tree_layout[player].value == TechTreeLayout.option_small_diamonds:
|
||||||
|
tech_names: List[str] = list(set(technology_table)-static_nodes)
|
||||||
|
tech_names.sort()
|
||||||
|
world.random.shuffle(tech_names)
|
||||||
|
while len(tech_names) > 4:
|
||||||
|
diamond_0, diamond_1, diamond_2, diamond_3 = tech_names[:4]
|
||||||
|
tech_names = tech_names[4:]
|
||||||
|
# 0 |
|
||||||
|
# 1 2 |
|
||||||
|
# 3 V
|
||||||
|
prerequisites[diamond_3] = [diamond_1, diamond_2]
|
||||||
|
prerequisites[diamond_2] = prerequisites[diamond_1] = [diamond_0]
|
||||||
|
world.tech_tree_layout_prerequisites[player] = prerequisites
|
||||||
|
return prerequisites
|
||||||
|
|
||||||
|
|
||||||
def set_rules(world: MultiWorld, player: int):
|
def set_rules(world: MultiWorld, player: int):
|
||||||
|
shapes = get_shapes(world, player)
|
||||||
if world.logic[player] != 'nologic':
|
if world.logic[player] != 'nologic':
|
||||||
from worlds.generic import Rules
|
from worlds.generic import Rules
|
||||||
allowed_packs = world.max_science_pack[player].get_allowed_packs()
|
allowed_packs = world.max_science_pack[player].get_allowed_packs()
|
||||||
|
@ -43,6 +63,12 @@ def set_rules(world: MultiWorld, player: int):
|
||||||
# loose nodes
|
# loose nodes
|
||||||
location = world.get_location(tech_name, player)
|
location = world.get_location(tech_name, player)
|
||||||
Rules.set_rule(location, technology.build_rule(allowed_packs, player))
|
Rules.set_rule(location, technology.build_rule(allowed_packs, player))
|
||||||
|
prequisites = shapes.get(tech_name)
|
||||||
|
if prequisites:
|
||||||
|
locations = [world.get_location(requisite, player) for requisite in prequisites]
|
||||||
|
Rules.add_rule(location, lambda state,
|
||||||
|
locations=locations: all(state.can_reach(loc) for loc in locations))
|
||||||
|
|
||||||
|
|
||||||
# get all technologies
|
# get all technologies
|
||||||
world.completion_condition[player] = lambda state: all(state.has(technology, player)
|
world.completion_condition[player] = lambda state: all(state.has(technology, player)
|
||||||
|
|
Loading…
Reference in New Issue