mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 04:01:32 -06:00
shapez: Typing Cleanup + Small Docs Rewordings (#5189)
Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import math
|
import math
|
||||||
from typing import Any, List, Dict, Tuple, Mapping
|
from typing import Mapping, Any
|
||||||
|
|
||||||
from Options import OptionError
|
from Options import OptionError
|
||||||
from .data.strings import OTHER, ITEMS, CATEGORY, LOCATIONS, SLOTDATA, GOALS, OPTIONS
|
from .data.strings import OTHER, ITEMS, CATEGORY, LOCATIONS, SLOTDATA, GOALS, OPTIONS
|
||||||
@@ -123,23 +123,23 @@ class ShapezWorld(World):
|
|||||||
# Defining instance attributes for each shapez world
|
# Defining instance attributes for each shapez world
|
||||||
# These are set to default values that should fail unit tests if not replaced with correct values
|
# These are set to default values that should fail unit tests if not replaced with correct values
|
||||||
self.location_count: int = 0
|
self.location_count: int = 0
|
||||||
self.level_logic: List[str] = []
|
self.level_logic: list[str] = []
|
||||||
self.upgrade_logic: List[str] = []
|
self.upgrade_logic: list[str] = []
|
||||||
self.level_logic_type: str = ""
|
self.level_logic_type: str = ""
|
||||||
self.upgrade_logic_type: str = ""
|
self.upgrade_logic_type: str = ""
|
||||||
self.random_logic_phase_length: List[int] = []
|
self.random_logic_phase_length: list[int] = []
|
||||||
self.category_random_logic_amounts: Dict[str, int] = {}
|
self.category_random_logic_amounts: dict[str, int] = {}
|
||||||
self.maxlevel: int = 0
|
self.maxlevel: int = 0
|
||||||
self.finaltier: int = 0
|
self.finaltier: int = 0
|
||||||
self.included_locations: Dict[str, Tuple[str, LocationProgressType]] = {}
|
self.included_locations: dict[str, tuple[str, LocationProgressType]] = {}
|
||||||
self.client_seed: int = 0
|
self.client_seed: int = 0
|
||||||
self.shapesanity_names: List[str] = []
|
self.shapesanity_names: list[str] = []
|
||||||
self.upgrade_traps_allowed: bool = False
|
self.upgrade_traps_allowed: bool = False
|
||||||
|
|
||||||
# Universal Tracker support
|
# Universal Tracker support
|
||||||
self.ut_active: bool = False
|
self.ut_active: bool = False
|
||||||
self.passthrough: Dict[str, any] = {}
|
self.passthrough: dict[str, Any] = {}
|
||||||
self.location_id_to_alias: Dict[int, str] = {}
|
self.location_id_to_alias: dict[int, str] = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def stage_generate_early(cls, multiworld: MultiWorld) -> None:
|
def stage_generate_early(cls, multiworld: MultiWorld) -> None:
|
||||||
@@ -315,7 +315,7 @@ class ShapezWorld(World):
|
|||||||
|
|
||||||
def create_items(self) -> None:
|
def create_items(self) -> None:
|
||||||
# Include guaranteed items (game mechanic unlocks and 7x4 big upgrades)
|
# Include guaranteed items (game mechanic unlocks and 7x4 big upgrades)
|
||||||
included_items: List[Item] = ([self.create_item(name) for name in buildings_processing.keys()]
|
included_items: list[Item] = ([self.create_item(name) for name in buildings_processing.keys()]
|
||||||
+ [self.create_item(name) for name in buildings_routing.keys()]
|
+ [self.create_item(name) for name in buildings_routing.keys()]
|
||||||
+ [self.create_item(name) for name in buildings_other.keys()]
|
+ [self.create_item(name) for name in buildings_other.keys()]
|
||||||
+ [self.create_item(name) for name in buildings_top_row.keys()]
|
+ [self.create_item(name) for name in buildings_top_row.keys()]
|
||||||
@@ -412,6 +412,6 @@ class ShapezWorld(World):
|
|||||||
**logic_type_cat_random_data, SLOTDATA.seed: self.client_seed,
|
**logic_type_cat_random_data, SLOTDATA.seed: self.client_seed,
|
||||||
SLOTDATA.shapesanity: self.shapesanity_names}
|
SLOTDATA.shapesanity: self.shapesanity_names}
|
||||||
|
|
||||||
def interpret_slot_data(self, slot_data: Dict[str, Any]) -> Dict[str, Any]:
|
def interpret_slot_data(self, slot_data: dict[str, Any]) -> dict[str, Any]:
|
||||||
"""Helper function for Universal Tracker"""
|
"""Helper function for Universal Tracker"""
|
||||||
return slot_data
|
return slot_data
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import random
|
import random
|
||||||
import typing
|
from typing import cast, Any
|
||||||
|
|
||||||
from Options import FreeText, NumericOption
|
from Options import FreeText, NumericOption
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ class FloatRangeText(FreeText, NumericOption):
|
|||||||
raise Exception(f"{value} is higher than maximum {self.range_end} for option {self.__class__.__name__}")
|
raise Exception(f"{value} is higher than maximum {self.range_end} for option {self.__class__.__name__}")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_text(cls, text: str) -> typing.Any:
|
def from_text(cls, text: str) -> Any:
|
||||||
return cls(text)
|
return cls(text)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -99,31 +99,31 @@ class FloatRangeText(FreeText, NumericOption):
|
|||||||
def get_option_name(cls, value: float) -> str:
|
def get_option_name(cls, value: float) -> str:
|
||||||
return str(value)
|
return str(value)
|
||||||
|
|
||||||
def __eq__(self, other: typing.Any):
|
def __eq__(self, other: Any):
|
||||||
if isinstance(other, NumericOption):
|
if isinstance(other, NumericOption):
|
||||||
return self.value == other.value
|
return self.value == other.value
|
||||||
else:
|
else:
|
||||||
return typing.cast(bool, self.value == other)
|
return cast(bool, self.value == other)
|
||||||
|
|
||||||
def __lt__(self, other: typing.Union[int, float, NumericOption]) -> bool:
|
def __lt__(self, other: int | float | NumericOption) -> bool:
|
||||||
if isinstance(other, NumericOption):
|
if isinstance(other, NumericOption):
|
||||||
return self.value < other.value
|
return self.value < other.value
|
||||||
else:
|
else:
|
||||||
return self.value < other
|
return self.value < other
|
||||||
|
|
||||||
def __le__(self, other: typing.Union[int, float, NumericOption]) -> bool:
|
def __le__(self, other: int | float | NumericOption) -> bool:
|
||||||
if isinstance(other, NumericOption):
|
if isinstance(other, NumericOption):
|
||||||
return self.value <= other.value
|
return self.value <= other.value
|
||||||
else:
|
else:
|
||||||
return self.value <= other
|
return self.value <= other
|
||||||
|
|
||||||
def __gt__(self, other: typing.Union[int, float, NumericOption]) -> bool:
|
def __gt__(self, other: int | float | NumericOption) -> bool:
|
||||||
if isinstance(other, NumericOption):
|
if isinstance(other, NumericOption):
|
||||||
return self.value > other.value
|
return self.value > other.value
|
||||||
else:
|
else:
|
||||||
return self.value > other
|
return self.value > other
|
||||||
|
|
||||||
def __ge__(self, other: typing.Union[int, float, NumericOption]) -> bool:
|
def __ge__(self, other: int | float | NumericOption) -> bool:
|
||||||
if isinstance(other, NumericOption):
|
if isinstance(other, NumericOption):
|
||||||
return self.value >= other.value
|
return self.value >= other.value
|
||||||
else:
|
else:
|
||||||
@@ -132,59 +132,59 @@ class FloatRangeText(FreeText, NumericOption):
|
|||||||
def __int__(self) -> int:
|
def __int__(self) -> int:
|
||||||
return int(self.value)
|
return int(self.value)
|
||||||
|
|
||||||
def __and__(self, other: typing.Any) -> int:
|
def __and__(self, other: Any) -> int:
|
||||||
raise TypeError("& operator not supported for float values")
|
raise TypeError("& operator not supported for float values")
|
||||||
|
|
||||||
def __floordiv__(self, other: typing.Any) -> int:
|
def __floordiv__(self, other: Any) -> int:
|
||||||
return int(self.value // float(other))
|
return int(self.value // float(other))
|
||||||
|
|
||||||
def __invert__(self) -> int:
|
def __invert__(self) -> int:
|
||||||
raise TypeError("~ operator not supported for float values")
|
raise TypeError("~ operator not supported for float values")
|
||||||
|
|
||||||
def __lshift__(self, other: typing.Any) -> int:
|
def __lshift__(self, other: Any) -> int:
|
||||||
raise TypeError("<< operator not supported for float values")
|
raise TypeError("<< operator not supported for float values")
|
||||||
|
|
||||||
def __mod__(self, other: typing.Any) -> float:
|
def __mod__(self, other: Any) -> float:
|
||||||
return self.value % float(other)
|
return self.value % float(other)
|
||||||
|
|
||||||
def __neg__(self) -> float:
|
def __neg__(self) -> float:
|
||||||
return -self.value
|
return -self.value
|
||||||
|
|
||||||
def __or__(self, other: typing.Any) -> int:
|
def __or__(self, other: Any) -> int:
|
||||||
raise TypeError("| operator not supported for float values")
|
raise TypeError("| operator not supported for float values")
|
||||||
|
|
||||||
def __pos__(self) -> float:
|
def __pos__(self) -> float:
|
||||||
return +self.value
|
return +self.value
|
||||||
|
|
||||||
def __rand__(self, other: typing.Any) -> int:
|
def __rand__(self, other: Any) -> int:
|
||||||
raise TypeError("& operator not supported for float values")
|
raise TypeError("& operator not supported for float values")
|
||||||
|
|
||||||
def __rfloordiv__(self, other: typing.Any) -> int:
|
def __rfloordiv__(self, other: Any) -> int:
|
||||||
return int(float(other) // self.value)
|
return int(float(other) // self.value)
|
||||||
|
|
||||||
def __rlshift__(self, other: typing.Any) -> int:
|
def __rlshift__(self, other: Any) -> int:
|
||||||
raise TypeError("<< operator not supported for float values")
|
raise TypeError("<< operator not supported for float values")
|
||||||
|
|
||||||
def __rmod__(self, other: typing.Any) -> float:
|
def __rmod__(self, other: Any) -> float:
|
||||||
return float(other) % self.value
|
return float(other) % self.value
|
||||||
|
|
||||||
def __ror__(self, other: typing.Any) -> int:
|
def __ror__(self, other: Any) -> int:
|
||||||
raise TypeError("| operator not supported for float values")
|
raise TypeError("| operator not supported for float values")
|
||||||
|
|
||||||
def __round__(self, ndigits: typing.Optional[int] = None) -> float:
|
def __round__(self, ndigits: int | None = None) -> float:
|
||||||
return round(self.value, ndigits)
|
return round(self.value, ndigits)
|
||||||
|
|
||||||
def __rpow__(self, base: typing.Any) -> typing.Any:
|
def __rpow__(self, base: Any) -> Any:
|
||||||
return base ** self.value
|
return base ** self.value
|
||||||
|
|
||||||
def __rrshift__(self, other: typing.Any) -> int:
|
def __rrshift__(self, other: Any) -> int:
|
||||||
raise TypeError(">> operator not supported for float values")
|
raise TypeError(">> operator not supported for float values")
|
||||||
|
|
||||||
def __rshift__(self, other: typing.Any) -> int:
|
def __rshift__(self, other: Any) -> int:
|
||||||
raise TypeError(">> operator not supported for float values")
|
raise TypeError(">> operator not supported for float values")
|
||||||
|
|
||||||
def __rxor__(self, other: typing.Any) -> int:
|
def __rxor__(self, other: Any) -> int:
|
||||||
raise TypeError("^ operator not supported for float values")
|
raise TypeError("^ operator not supported for float values")
|
||||||
|
|
||||||
def __xor__(self, other: typing.Any) -> int:
|
def __xor__(self, other: Any) -> int:
|
||||||
raise TypeError("^ operator not supported for float values")
|
raise TypeError("^ operator not supported for float values")
|
||||||
|
@@ -1,14 +1,13 @@
|
|||||||
import itertools
|
import itertools
|
||||||
import time
|
import time
|
||||||
from typing import Dict, List
|
|
||||||
|
|
||||||
from worlds.shapez.data.strings import SHAPESANITY, REGIONS
|
from worlds.shapez.data.strings import SHAPESANITY, REGIONS
|
||||||
|
|
||||||
shapesanity_simple: Dict[str, str] = {}
|
shapesanity_simple: dict[str, str] = {}
|
||||||
shapesanity_1_4: Dict[str, str] = {}
|
shapesanity_1_4: dict[str, str] = {}
|
||||||
shapesanity_two_sided: Dict[str, str] = {}
|
shapesanity_two_sided: dict[str, str] = {}
|
||||||
shapesanity_three_parts: Dict[str, str] = {}
|
shapesanity_three_parts: dict[str, str] = {}
|
||||||
shapesanity_four_parts: Dict[str, str] = {}
|
shapesanity_four_parts: dict[str, str] = {}
|
||||||
subshape_names = [SHAPESANITY.circle, SHAPESANITY.square, SHAPESANITY.star, SHAPESANITY.windmill]
|
subshape_names = [SHAPESANITY.circle, SHAPESANITY.square, SHAPESANITY.star, SHAPESANITY.windmill]
|
||||||
color_names = [SHAPESANITY.red, SHAPESANITY.blue, SHAPESANITY.green, SHAPESANITY.yellow, SHAPESANITY.purple,
|
color_names = [SHAPESANITY.red, SHAPESANITY.blue, SHAPESANITY.green, SHAPESANITY.yellow, SHAPESANITY.purple,
|
||||||
SHAPESANITY.cyan, SHAPESANITY.white, SHAPESANITY.uncolored]
|
SHAPESANITY.cyan, SHAPESANITY.white, SHAPESANITY.uncolored]
|
||||||
@@ -16,7 +15,7 @@ short_subshapes = ["C", "R", "S", "W"]
|
|||||||
short_colors = ["b", "c", "g", "p", "r", "u", "w", "y"]
|
short_colors = ["b", "c", "g", "p", "r", "u", "w", "y"]
|
||||||
|
|
||||||
|
|
||||||
def color_to_needed_building(color_list: List[str]) -> str:
|
def color_to_needed_building(color_list: list[str]) -> str:
|
||||||
for next_color in color_list:
|
for next_color in color_list:
|
||||||
if next_color in [SHAPESANITY.yellow, SHAPESANITY.purple, SHAPESANITY.cyan, SHAPESANITY.white,
|
if next_color in [SHAPESANITY.yellow, SHAPESANITY.purple, SHAPESANITY.cyan, SHAPESANITY.white,
|
||||||
"y", "p", "c", "w"]:
|
"y", "p", "c", "w"]:
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
Die Maximalwerte von `goal_amount` und `shapesanity_amount` sind fest eingebaute Einstellungen, die das Datenpaket des
|
Die Maximalwerte von `goal_amount` und `shapesanity_amount` sind fest eingebaute Einstellungen, die das Datenpaket des
|
||||||
Spiels beeinflussen. Sie sind in einer Datei names `options.json` innerhalb der APWorld festgelegt. Durch das Ändern
|
Spiels beeinflussen. Sie sind in einer Datei names `options.json` innerhalb der APWorld festgelegt. Durch das Ändern
|
||||||
dieser Werte erschaffst du eine custom APWorld, die nur auf deinem PC existiert.
|
dieser Werte erschaffst du eine custom Version der APWorld, die nur auf deinem PC existiert.
|
||||||
|
|
||||||
## Wie du die Datenpaket-Einstellungen änderst
|
## Wie du die Datenpaket-Einstellungen änderst
|
||||||
|
|
||||||
@@ -18,17 +18,18 @@ ordnungsgemäß befolgt wird. Anwendung auf eigene Gefahr.
|
|||||||
- `max_shapesanity` kann nicht weniger als `4` sein, da dies die benötigte Mindestanzahl zum Verhindern von
|
- `max_shapesanity` kann nicht weniger als `4` sein, da dies die benötigte Mindestanzahl zum Verhindern von
|
||||||
FillErrors ist.
|
FillErrors ist.
|
||||||
- `max_shapesanity` kann auch nicht mehr als `75800` sein, da dies die maximale Anzahl an möglichen Shapesanity-Namen
|
- `max_shapesanity` kann auch nicht mehr als `75800` sein, da dies die maximale Anzahl an möglichen Shapesanity-Namen
|
||||||
ist. Ansonsten könnte die Generierung der Multiworld fehlschlagen.
|
ist. Das Generieren der Multiworld wird fehlschlagen, falls die `shapesanity_amount`-Option auf einen höheren Wert
|
||||||
|
gesetzt wird.
|
||||||
- `max_levels_and_upgrades` kann nicht weniger als `27` sein, da dies die Mindestanzahl für das `mam`-Ziel ist.
|
- `max_levels_and_upgrades` kann nicht weniger als `27` sein, da dies die Mindestanzahl für das `mam`-Ziel ist.
|
||||||
5. Schließe die Zip-Datei und benenne sie zurück zu `shapez.apworld`.
|
5. Schließe die Zip-Datei und benenne sie zurück zu `shapez.apworld`.
|
||||||
|
|
||||||
## Warum muss ich das ganze selbst machen?
|
## Warum muss ich das ganze selbst machen?
|
||||||
|
|
||||||
Alle Spiele in Archipelago müssen eine Liste aller möglichen Locations **unabhängig der Spieler-Optionen**
|
Alle Spiele in Archipelago müssen eine Liste aller möglichen Locations **unabhängig der Spieler-Optionen**
|
||||||
bereitstellen. Diese Listen aller in einer Multiworld inkludierten Spiele werden in den Daten der Multiworld gespeichert
|
bereitstellen. Diese Listen aller in einer Multiworld inkludierten Spiele werden in den Daten der Multiworld gespeichert
|
||||||
und an alle verbundenen Clients gesendet. Je mehr mögliche Locations, desto größer das Datenpaket. Und mit ~80000
|
und an alle verbundenen Clients gesendet. Je mehr mögliche Locations, desto größer das Datenpaket. Und mit ~80000
|
||||||
möglichen Locations hatte shapez zu einem gewissen Zeitpunkt ein (von der Datenmenge her) größeres Datenpaket als alle
|
möglichen Locations hatte shapez zu einem gewissen Zeitpunkt ein (von der Datenmenge her) größeres Datenpaket als alle
|
||||||
supporteten Spiele zusammen. Um also diese Datenmenge zu reduzieren wurden die ausgeschriebenen
|
Core-verifizierten Spiele zusammen. Um also diese Datenmenge zu reduzieren, wurden die ausgeschriebenen
|
||||||
Shapesanity-Locations-Namen (`Shapesanity Uncolored Circle`, `Shapesanity Blue Rectangle`, ...) durch standardisierte
|
Shapesanity-Locations-Namen (`Shapesanity Uncolored Circle`, `Shapesanity Blue Rectangle`, ...) durch standardisierte
|
||||||
Namen (`Shapesanity 1`, `Shapesanity 2`, ...) ersetzt. Durch das Ändern dieser Maximalwerte, und damit das Erstellen
|
Namen (`Shapesanity 1`, `Shapesanity 2`, ...) ersetzt. Durch das Ändern dieser Maximalwerte, und damit das Erstellen
|
||||||
einer custom APWorld, kannst du die Anzahl der möglichen Locations erhöhen, wirst aber auch gleichzeitig das Datenpaket
|
einer custom APWorld, kannst du die Anzahl der möglichen Locations erhöhen, wirst aber auch gleichzeitig das Datenpaket
|
||||||
|
@@ -1,14 +1,14 @@
|
|||||||
# Guide to change maximum locations in shapez
|
# Guide to change the maximum amount of locations in shapez
|
||||||
|
|
||||||
## Where do I find the settings to increase/decrease the amount of possible locations?
|
## Where do I find the settings to increase/decrease the amount of possible locations?
|
||||||
|
|
||||||
The maximum values of the `goal_amount` and `shapesanity_amount` are hardcoded settings that affect the datapackage.
|
The maximum values of the `goal_amount` and `shapesanity_amount` options are hardcoded settings that affect the
|
||||||
They are stored in a file called `options.json` inside the apworld. By changing them, you will create a custom apworld
|
datapackage. They are stored in a file called `options.json` inside the apworld. By changing them, you will create a
|
||||||
on your local machine.
|
custom version on your local machine.
|
||||||
|
|
||||||
## How to change datapackage options
|
## How to change datapackage settings
|
||||||
|
|
||||||
This tutorial is for advanced users and can result in the software not working properly, if not read carefully.
|
This tutorial is intended for advanced users and can result in the software not working properly, if not read carefully.
|
||||||
Proceed at your own risk.
|
Proceed at your own risk.
|
||||||
|
|
||||||
1. Go to `<AP installation>/lib/worlds`.
|
1. Go to `<AP installation>/lib/worlds`.
|
||||||
@@ -17,17 +17,17 @@ Proceed at your own risk.
|
|||||||
4. Edit the values in this file to your desire and save the file.
|
4. Edit the values in this file to your desire and save the file.
|
||||||
- `max_shapesanity` cannot be lower than `4`, as this is the minimum amount to prevent FillErrors.
|
- `max_shapesanity` cannot be lower than `4`, as this is the minimum amount to prevent FillErrors.
|
||||||
- `max_shapesanity` also cannot be higher than `75800`, as this is the maximum amount of possible shapesanity names.
|
- `max_shapesanity` also cannot be higher than `75800`, as this is the maximum amount of possible shapesanity names.
|
||||||
Else the multiworld generation might fail.
|
Multiworld generation will fail if the `shapesanity_amount` options is set to a higher value.
|
||||||
- `max_levels_and_upgrades` cannot be lower than `27`, as this is the minimum amount for the `mam` goal to properly
|
- `max_levels_and_upgrades` cannot be lower than `27`, as this is the minimum amount for the `mam` goal to properly
|
||||||
work.
|
work.
|
||||||
5. Close the zip and rename it back to `shapez.apworld`.
|
5. Close the zip file and rename it back to `shapez.apworld`.
|
||||||
|
|
||||||
## Why do I have to do this manually?
|
## Why do I have to do this manually?
|
||||||
|
|
||||||
For every game in Archipelago, there must be a list of all possible locations, **regardless of player options**. When
|
For every game in Archipelago, there must be a list of all possible locations, **regardless of player options**. When
|
||||||
generating a multiworld, a list of all locations of all included games will be saved in the multiworld data and sent to
|
generating a multiworld, a list of all locations of all included games will be saved in the multiworld's data and sent
|
||||||
all clients. The higher the amount of possible locations, the bigger the datapackage. And having ~80000 possible
|
to all clients. The higher the amount of possible locations, the bigger the datapackage. And having ~80000 possible
|
||||||
locations at one point made the datapackage for shapez bigger than all other supported games combined. So to reduce the
|
locations at one point made the datapackage for shapez bigger than all other core-verified games combined. So, to reduce
|
||||||
datapackage of shapez, the locations for shapesanity are named `Shapesanity 1`, `Shapesanity 2` etc. instead of their
|
the datapackage size of shapez, the locations for shapesanity are named `Shapesanity 1`, `Shapesanity 2` etc. instead of
|
||||||
actual names. By creating a custom apworld, you can increase the amount of possible locations, but you will also
|
their actual names. By creating a custom version of the apworld, you can increase the amount of possible locations, but
|
||||||
increase the size of the datapackage at the same time.
|
you will also increase the size of the datapackage at the same time.
|
||||||
|
@@ -19,25 +19,27 @@ Zusätzlich gibt es zu diesem Spiel "Datenpaket-Einstellungen", die du nach
|
|||||||
|
|
||||||
Alle Belohnungen aus den Tutorial-Level (das Freischalten von Gebäuden und Spielmechaniken) und Verbesserungen durch
|
Alle Belohnungen aus den Tutorial-Level (das Freischalten von Gebäuden und Spielmechaniken) und Verbesserungen durch
|
||||||
Upgrades werden dem Itempool der Multiworld hinzugefügt. Außerdem werden, wenn so in den Spieler-Optionen festgelegt,
|
Upgrades werden dem Itempool der Multiworld hinzugefügt. Außerdem werden, wenn so in den Spieler-Optionen festgelegt,
|
||||||
die Bedingungen zum Abschließen eines Levels und zum Kaufen der Upgrades randomisiert.
|
die Bedingungen zum Abschließen eines Levels und zum Kaufen der Upgrades randomisiert und die Reihenfolge der Gebäude
|
||||||
|
in deinen Toolbars (Haupt- und Kabelebene) gemischt.
|
||||||
|
|
||||||
## Was ist das Ziel von shapez in Archipelago?
|
## Was ist das Ziel von shapez in Archipelago?
|
||||||
|
|
||||||
Da das Spiel eigentlich kein konkretes Ziel (nach dem Tutorial) hat, kann man sich zwischen (momentan) 4 verschiedenen
|
Da das Spiel eigentlich kein konkretes Ziel, welches das Ende des Spiels bedeuten würde, hat, kann man sich zwischen
|
||||||
Zielen entscheiden:
|
(aktuell) 4 verschiedenen Zielen entscheiden:
|
||||||
1. Vanilla: Schließe Level 26 ab (eigentlich das Ende des Tutorials).
|
1. Vanilla: Schließe Level 26 ab (eigentlich das Ende des Tutorials).
|
||||||
2. MAM: Schließe ein bestimmtes Level nach Level 26 ab, das zuvor in den Spieler-Optionen festgelegt wurde. Es ist
|
2. MAM: Schließe ein bestimmtes Level nach Level 26 ab, das zuvor in den Spieler-Optionen festgelegt wurde. Es ist
|
||||||
empfohlen, eine Maschine zu bauen, die alles automatisch herstellt ("Make-Anything-Machine", kurz MAM).
|
empfohlen, eine Maschine zu bauen, die alles automatisch herstellt ("Make-Anything-Machine", kurz MAM).
|
||||||
3. Even Fasterer: Kaufe alle Upgrades bis zu einer in den Spieler-Optionen festgelegten Stufe (nach Stufe 8).
|
3. Even Fasterer: Kaufe alle Upgrades bis zu einer in den Spieler-Optionen festgelegten Stufe (nach Stufe VIII (8)).
|
||||||
4. Efficiency III: Liefere 256 Blaupausen-Formen pro Sekunde ins Zentrum.
|
4. Efficiency III: Liefere 256 Blaupausen-Formen pro Sekunde ins Zentrum.
|
||||||
|
|
||||||
## Welche Items können in den Welten anderer Spieler erscheinen?
|
## Welche Items können in den Welten anderer Spieler erscheinen?
|
||||||
|
|
||||||
- Freischalten verschiedener Gebäude
|
- Gebäude
|
||||||
- Blaupausen freischalten
|
- Blaupausen freischalten
|
||||||
- Große Upgrades (addiert 1 zum Geschwindigkeitsmultiplikator)
|
- Upgrades
|
||||||
- Kleine Upgrades (addiert 0.1 zum Geschwindigkeitsmultiplikator)
|
- Große Upgrades (addiert 1 zum Geschwindigkeitsmultiplikator)
|
||||||
- Andere ungewöhnliche Upgrades (optional)
|
- Kleine Upgrades (addiert 0.1 zum Geschwindigkeitsmultiplikator)
|
||||||
|
- Andere ungewöhnliche (auch negative) Upgrades (optional)
|
||||||
- Verschiedene Bündel, die bestimmte Formen enthalten
|
- Verschiedene Bündel, die bestimmte Formen enthalten
|
||||||
- Fallen, die bestimmte Formen aus dem Zentrum dränieren (ja, das Wort gibt es)
|
- Fallen, die bestimmte Formen aus dem Zentrum dränieren (ja, das Wort gibt es)
|
||||||
- Fallen, die zufällige Gebäude oder andere Spielmechaniken betreffen
|
- Fallen, die zufällige Gebäude oder andere Spielmechaniken betreffen
|
||||||
@@ -45,7 +47,7 @@ empfohlen, eine Maschine zu bauen, die alles automatisch herstellt ("Make-Anythi
|
|||||||
## Was ist eine Location / ein Check?
|
## Was ist eine Location / ein Check?
|
||||||
|
|
||||||
- Level (minimum 1-25, bis zu 499 je nach Spieler-Optionen, mit zusätzlichen Checks für Level 1 und 20)
|
- Level (minimum 1-25, bis zu 499 je nach Spieler-Optionen, mit zusätzlichen Checks für Level 1 und 20)
|
||||||
- Upgrades (minimum Stufen II-VIII (2-8), bis zu D (500) je nach Spieler-Optionen)
|
- Upgrades (minimum Stufen II-VIII (2-8), bis zu D (500), je nach Spieler-Optionen)
|
||||||
- Bestimmte Formen mindestens einmal ins Zentrum liefern ("Shapesanity", bis zu 1000 zufällig gewählte Definitionen)
|
- Bestimmte Formen mindestens einmal ins Zentrum liefern ("Shapesanity", bis zu 1000 zufällig gewählte Definitionen)
|
||||||
- Errungenschaften (bis zu 45)
|
- Errungenschaften (bis zu 45)
|
||||||
|
|
||||||
|
@@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
shapez is an automation game about cutting, rotating, stacking, and painting shapes, that you extract from randomly
|
shapez is an automation game about cutting, rotating, stacking, and painting shapes, that you extract from randomly
|
||||||
generated patches on an infinite canvas, and sending them to the hub to complete levels. The "tutorial", where you
|
generated patches on an infinite canvas, and sending them to the hub to complete levels. The "tutorial", where you
|
||||||
unlock a new building or game mechanic (almost) each level, lasts until level 26, where you unlock freeplay with
|
unlock a new building or game mechanic (almost) each level, lasts until level 26, which unlocks freeplay with
|
||||||
infinitely more levels, that require a new, randomly generated shape. Alongside the levels, you can unlock upgrades,
|
infinitely more levels, that each require a new, randomly generated shape. Alongside the levels, you can unlock
|
||||||
that make your buildings work faster.
|
upgrades, that make your buildings work faster.
|
||||||
|
|
||||||
## Where is the options page?
|
## Where is the options page?
|
||||||
|
|
||||||
@@ -17,29 +17,30 @@ There are also some advanced "datapackage settings" that can be changed by follo
|
|||||||
|
|
||||||
## What does randomization do to this game?
|
## What does randomization do to this game?
|
||||||
|
|
||||||
Buildings and gameplay mechanics, that you normally unlock by completing a level, and upgrade improvements are put
|
Buildings and gameplay mechanics, which you normally unlock by completing a level, and upgrade improvements are put
|
||||||
into the item pool of the multiworld. Also, if enabled, the requirements for completing a level or buying an upgrade are
|
into the item pool of the multiworld. You can also randomize the requirements for completing a level or buying an
|
||||||
randomized.
|
upgrade and shuffle the order of building in your toolbars (main and wires layer).
|
||||||
|
|
||||||
## What is the goal of shapez in Archipelago?
|
## What is the goal of shapez in Archipelago?
|
||||||
|
|
||||||
As the game has no actual goal where the game ends, there are (currently) 4 different goals you can choose from in the
|
As the game has no actual goal that would represent the end of the game, there are (currently) 4 different goals you
|
||||||
player options:
|
can choose from in the player options:
|
||||||
1. Vanilla: Complete level 26 (the end of the tutorial).
|
1. Vanilla: Complete level 26 (the end of the tutorial).
|
||||||
2. MAM: Complete a player-specified level after level 26. It's recommended to build a Make-Anything-Machine (MAM).
|
2. MAM: Complete a player-specified level after level 26. It's recommended to build a Make-Anything-Machine (MAM).
|
||||||
3. Even Fasterer: Upgrade everything to a player-specified tier after tier 8.
|
3. Even Fasterer: Upgrade everything to a player-specified tier after tier VIII (8).
|
||||||
4. Efficiency III: Deliver 256 blueprint shapes per second to the hub.
|
4. Efficiency III: Deliver 256 blueprint shapes per second to the hub.
|
||||||
|
|
||||||
## Which items can be in another player's world?
|
## Which items can be in another player's world?
|
||||||
|
|
||||||
- Unlock different buildings
|
- Buildings
|
||||||
- Unlock blueprints
|
- Unlocking blueprints
|
||||||
- Big upgrade improvements (adds 1 to the multiplier)
|
- Upgrade improvements
|
||||||
- Small upgrade improvements (adds .1 to the multiplier)
|
- Big improvements, adding 1 to the multiplier
|
||||||
- Other unusual upgrade improvements (optional)
|
- Small improvements, adding 0.1 to the multiplier
|
||||||
|
- Optional: Other, rather unusual and even bad, improvements
|
||||||
- Different shapes bundles
|
- Different shapes bundles
|
||||||
- Inventory draining traps
|
- Inventory draining traps
|
||||||
- Different traps afflicting random buildings and game mechanics
|
- Different traps affecting random buildings and game mechanics
|
||||||
|
|
||||||
## What is considered a location check?
|
## What is considered a location check?
|
||||||
|
|
||||||
@@ -61,5 +62,4 @@ Here's a cheat sheet:
|
|||||||
## Can I use other mods alongside the AP client?
|
## Can I use other mods alongside the AP client?
|
||||||
|
|
||||||
At the moment, compatibility with other mods is not supported, but not forbidden. Gameplay altering mods will most
|
At the moment, compatibility with other mods is not supported, but not forbidden. Gameplay altering mods will most
|
||||||
likely crash the game or disable loading the afflicted mods, while QoL mods might work without problems. Try at your own
|
likely break the game in some way, while small QoL mods might work without problems. Try at your own risk.
|
||||||
risk.
|
|
||||||
|
@@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
- Archipelago von der [Archipelago-Release-Seite](https://github.com/ArchipelagoMW/Archipelago/releases)
|
- Archipelago von der [Archipelago-Release-Seite](https://github.com/ArchipelagoMW/Archipelago/releases)
|
||||||
* (Für den Text-Client)
|
* (Für den Text-Client)
|
||||||
* (Alternativ kannst du auch die eingebaute Konsole (nur lesbar) nutzen, indem du beim Starten des Spiels den
|
* (Alternativ kannst du auch die eingebaute Konsole nutzen, indem du das Spiel mit dem `-dev`-Parameter
|
||||||
`-dev`-Parameter verwendest)
|
startest und jede Nachricht als `AP.sendAPMessage("<Nachricht>"")` schreibst)
|
||||||
- Universal Tracker (schau im `#future-game-design`-Thread für UT auf dem Discord-Server nach der aktuellen Anleitung)
|
- Universal Tracker (schau im Kanal von UT auf dem Discord-Server nach der aktuellen Anleitung und für weitere
|
||||||
|
Informationen)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
@@ -16,9 +16,9 @@
|
|||||||
|
|
||||||
- Archipelago from the [Archipelago Releases Page](https://github.com/ArchipelagoMW/Archipelago/releases)
|
- Archipelago from the [Archipelago Releases Page](https://github.com/ArchipelagoMW/Archipelago/releases)
|
||||||
* (Only for the TextClient)
|
* (Only for the TextClient)
|
||||||
* (If you want, you can use the built-in console as a read-only text client by launching the game
|
* (You can alternatively use the built-in console by launching the game with the `-dev` parameter and typing
|
||||||
with the `-dev` parameter)
|
`AP.sendAPMessage("<message>"")`)
|
||||||
- Universal Tracker (check UT's `#future-game-design` thread in the discord server for instructions)
|
- Universal Tracker (check UT's channel in the discord server for more information and instructions)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
from typing import Dict, Callable, Any, List
|
from typing import Callable, Any
|
||||||
|
|
||||||
from BaseClasses import Item, ItemClassification as IClass
|
from BaseClasses import Item, ItemClassification as IClass
|
||||||
from .options import ShapezOptions
|
from .options import ShapezOptions
|
||||||
@@ -37,7 +37,7 @@ def always_trap(options: ShapezOptions) -> IClass:
|
|||||||
# would be unreasonably complicated and time-consuming.
|
# would be unreasonably complicated and time-consuming.
|
||||||
# Some buildings are not needed to complete the game, but are "logically needed" for the "MAM" achievement.
|
# Some buildings are not needed to complete the game, but are "logically needed" for the "MAM" achievement.
|
||||||
|
|
||||||
buildings_processing: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
buildings_processing: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.cutter: always_progression,
|
ITEMS.cutter: always_progression,
|
||||||
ITEMS.cutter_quad: always_progression,
|
ITEMS.cutter_quad: always_progression,
|
||||||
ITEMS.rotator: always_progression,
|
ITEMS.rotator: always_progression,
|
||||||
@@ -50,7 +50,7 @@ buildings_processing: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
|||||||
ITEMS.color_mixer: always_progression,
|
ITEMS.color_mixer: always_progression,
|
||||||
}
|
}
|
||||||
|
|
||||||
buildings_routing: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
buildings_routing: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.balancer: always_progression,
|
ITEMS.balancer: always_progression,
|
||||||
ITEMS.comp_merger: always_progression,
|
ITEMS.comp_merger: always_progression,
|
||||||
ITEMS.comp_splitter: always_progression,
|
ITEMS.comp_splitter: always_progression,
|
||||||
@@ -58,12 +58,12 @@ buildings_routing: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
|||||||
ITEMS.tunnel_tier_ii: is_mam_achievement_included,
|
ITEMS.tunnel_tier_ii: is_mam_achievement_included,
|
||||||
}
|
}
|
||||||
|
|
||||||
buildings_other: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
buildings_other: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.trash: always_progression,
|
ITEMS.trash: always_progression,
|
||||||
ITEMS.extractor_chain: always_useful
|
ITEMS.extractor_chain: always_useful
|
||||||
}
|
}
|
||||||
|
|
||||||
buildings_top_row: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
buildings_top_row: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.belt_reader: is_mam_achievement_included,
|
ITEMS.belt_reader: is_mam_achievement_included,
|
||||||
ITEMS.storage: is_achievements_included,
|
ITEMS.storage: is_achievements_included,
|
||||||
ITEMS.switch: always_progression,
|
ITEMS.switch: always_progression,
|
||||||
@@ -71,18 +71,18 @@ buildings_top_row: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
|||||||
ITEMS.display: always_useful
|
ITEMS.display: always_useful
|
||||||
}
|
}
|
||||||
|
|
||||||
buildings_wires: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
buildings_wires: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.wires: always_progression,
|
ITEMS.wires: always_progression,
|
||||||
ITEMS.const_signal: always_progression,
|
ITEMS.const_signal: always_progression,
|
||||||
ITEMS.logic_gates: is_mam_achievement_included,
|
ITEMS.logic_gates: is_mam_achievement_included,
|
||||||
ITEMS.virtual_proc: is_mam_achievement_included
|
ITEMS.virtual_proc: is_mam_achievement_included
|
||||||
}
|
}
|
||||||
|
|
||||||
gameplay_unlocks: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
gameplay_unlocks: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.blueprints: is_achievements_included
|
ITEMS.blueprints: is_achievements_included
|
||||||
}
|
}
|
||||||
|
|
||||||
upgrades: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
upgrades: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.upgrade_big_belt: always_progression,
|
ITEMS.upgrade_big_belt: always_progression,
|
||||||
ITEMS.upgrade_big_miner: always_useful,
|
ITEMS.upgrade_big_miner: always_useful,
|
||||||
ITEMS.upgrade_big_proc: always_useful,
|
ITEMS.upgrade_big_proc: always_useful,
|
||||||
@@ -93,7 +93,7 @@ upgrades: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
|||||||
ITEMS.upgrade_small_paint: always_filler
|
ITEMS.upgrade_small_paint: always_filler
|
||||||
}
|
}
|
||||||
|
|
||||||
whacky_upgrades: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
whacky_upgrades: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.upgrade_gigantic_belt: always_progression,
|
ITEMS.upgrade_gigantic_belt: always_progression,
|
||||||
ITEMS.upgrade_gigantic_miner: always_useful,
|
ITEMS.upgrade_gigantic_miner: always_useful,
|
||||||
ITEMS.upgrade_gigantic_proc: always_useful,
|
ITEMS.upgrade_gigantic_proc: always_useful,
|
||||||
@@ -106,7 +106,7 @@ whacky_upgrades: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
|||||||
ITEMS.upgrade_small_random: always_filler,
|
ITEMS.upgrade_small_random: always_filler,
|
||||||
}
|
}
|
||||||
|
|
||||||
whacky_upgrade_traps: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
whacky_upgrade_traps: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.trap_upgrade_belt: always_trap,
|
ITEMS.trap_upgrade_belt: always_trap,
|
||||||
ITEMS.trap_upgrade_miner: always_trap,
|
ITEMS.trap_upgrade_miner: always_trap,
|
||||||
ITEMS.trap_upgrade_proc: always_trap,
|
ITEMS.trap_upgrade_proc: always_trap,
|
||||||
@@ -117,13 +117,13 @@ whacky_upgrade_traps: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
|||||||
ITEMS.trap_upgrade_demonic_paint: always_trap,
|
ITEMS.trap_upgrade_demonic_paint: always_trap,
|
||||||
}
|
}
|
||||||
|
|
||||||
bundles: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
bundles: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.bundle_blueprint: always_filler,
|
ITEMS.bundle_blueprint: always_filler,
|
||||||
ITEMS.bundle_level: always_filler,
|
ITEMS.bundle_level: always_filler,
|
||||||
ITEMS.bundle_upgrade: always_filler
|
ITEMS.bundle_upgrade: always_filler
|
||||||
}
|
}
|
||||||
|
|
||||||
standard_traps: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
standard_traps: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.trap_locked: always_trap,
|
ITEMS.trap_locked: always_trap,
|
||||||
ITEMS.trap_throttled: always_trap,
|
ITEMS.trap_throttled: always_trap,
|
||||||
ITEMS.trap_malfunction: always_trap,
|
ITEMS.trap_malfunction: always_trap,
|
||||||
@@ -131,22 +131,22 @@ standard_traps: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
|||||||
ITEMS.trap_clear_belts: always_trap,
|
ITEMS.trap_clear_belts: always_trap,
|
||||||
}
|
}
|
||||||
|
|
||||||
random_draining_trap: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
random_draining_trap: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.trap_draining_inv: always_trap
|
ITEMS.trap_draining_inv: always_trap
|
||||||
}
|
}
|
||||||
|
|
||||||
split_draining_traps: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
split_draining_traps: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.trap_draining_blueprint: always_trap,
|
ITEMS.trap_draining_blueprint: always_trap,
|
||||||
ITEMS.trap_draining_level: always_trap,
|
ITEMS.trap_draining_level: always_trap,
|
||||||
ITEMS.trap_draining_upgrade: always_trap
|
ITEMS.trap_draining_upgrade: always_trap
|
||||||
}
|
}
|
||||||
|
|
||||||
belt_and_extractor: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
belt_and_extractor: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
ITEMS.belt: always_progression,
|
ITEMS.belt: always_progression,
|
||||||
ITEMS.extractor: always_progression
|
ITEMS.extractor: always_progression
|
||||||
}
|
}
|
||||||
|
|
||||||
item_table: Dict[str, Callable[[ShapezOptions], IClass]] = {
|
item_table: dict[str, Callable[[ShapezOptions], IClass]] = {
|
||||||
**buildings_processing,
|
**buildings_processing,
|
||||||
**buildings_routing,
|
**buildings_routing,
|
||||||
**buildings_other,
|
**buildings_other,
|
||||||
@@ -205,10 +205,10 @@ def trap(random: float, split_draining: bool, whacky_allowed: bool) -> str:
|
|||||||
return random_choice_nested(random, pool)
|
return random_choice_nested(random, pool)
|
||||||
|
|
||||||
|
|
||||||
def random_choice_nested(random: float, nested: List[Any]) -> Any:
|
def random_choice_nested(random: float, nested: list[Any]) -> Any:
|
||||||
"""Helper function for getting a random element from a nested list."""
|
"""Helper function for getting a random element from a nested list."""
|
||||||
current: Any = nested
|
current: Any = nested
|
||||||
while isinstance(current, List):
|
while isinstance(current, list):
|
||||||
index_float = random*len(current)
|
index_float = random*len(current)
|
||||||
current = current[int(index_float)]
|
current = current[int(index_float)]
|
||||||
random = index_float-int(index_float)
|
random = index_float-int(index_float)
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
from random import Random
|
from random import Random
|
||||||
from typing import List, Tuple, Dict, Optional, Callable
|
from typing import Callable
|
||||||
|
|
||||||
from BaseClasses import Location, LocationProgressType, Region
|
from BaseClasses import Location, LocationProgressType, Region
|
||||||
from .data.strings import CATEGORY, LOCATIONS, REGIONS, OPTIONS, GOALS, OTHER, SHAPESANITY
|
from .data.strings import CATEGORY, LOCATIONS, REGIONS, OPTIONS, GOALS, OTHER, SHAPESANITY
|
||||||
@@ -7,7 +7,7 @@ from .options import max_shapesanity, max_levels_and_upgrades
|
|||||||
|
|
||||||
categories = [CATEGORY.belt, CATEGORY.miner, CATEGORY.processors, CATEGORY.painting]
|
categories = [CATEGORY.belt, CATEGORY.miner, CATEGORY.processors, CATEGORY.painting]
|
||||||
|
|
||||||
translate: List[Tuple[int, str]] = [
|
translate: list[tuple[int, str]] = [
|
||||||
(1000, "M"),
|
(1000, "M"),
|
||||||
(900, "CM"),
|
(900, "CM"),
|
||||||
(500, "D"),
|
(500, "D"),
|
||||||
@@ -148,17 +148,17 @@ location_description = { # TODO change keys to global strings
|
|||||||
"windmill.",
|
"windmill.",
|
||||||
}
|
}
|
||||||
|
|
||||||
shapesanity_simple: Dict[str, str] = {}
|
shapesanity_simple: dict[str, str] = {}
|
||||||
shapesanity_1_4: Dict[str, str] = {}
|
shapesanity_1_4: dict[str, str] = {}
|
||||||
shapesanity_two_sided: Dict[str, str] = {}
|
shapesanity_two_sided: dict[str, str] = {}
|
||||||
shapesanity_three_parts: Dict[str, str] = {}
|
shapesanity_three_parts: dict[str, str] = {}
|
||||||
shapesanity_four_parts: Dict[str, str] = {}
|
shapesanity_four_parts: dict[str, str] = {}
|
||||||
|
|
||||||
level_locations: List[str] = ([LOCATIONS.level(1, 1), LOCATIONS.level(20, 1), LOCATIONS.level(20, 2)]
|
level_locations: list[str] = ([LOCATIONS.level(1, 1), LOCATIONS.level(20, 1), LOCATIONS.level(20, 2)]
|
||||||
+ [LOCATIONS.level(x) for x in range(1, max_levels_and_upgrades)])
|
+ [LOCATIONS.level(x) for x in range(1, max_levels_and_upgrades)])
|
||||||
upgrade_locations: List[str] = [LOCATIONS.upgrade(cat, roman(x))
|
upgrade_locations: list[str] = [LOCATIONS.upgrade(cat, roman(x))
|
||||||
for cat in categories for x in range(2, max_levels_and_upgrades+1)]
|
for cat in categories for x in range(2, max_levels_and_upgrades+1)]
|
||||||
achievement_locations: List[str] = [LOCATIONS.my_eyes, LOCATIONS.painter, LOCATIONS.cutter, LOCATIONS.rotater,
|
achievement_locations: list[str] = [LOCATIONS.my_eyes, LOCATIONS.painter, LOCATIONS.cutter, LOCATIONS.rotater,
|
||||||
LOCATIONS.wait_they_stack, LOCATIONS.wires, LOCATIONS.storage, LOCATIONS.freedom,
|
LOCATIONS.wait_they_stack, LOCATIONS.wires, LOCATIONS.storage, LOCATIONS.freedom,
|
||||||
LOCATIONS.the_logo, LOCATIONS.to_the_moon, LOCATIONS.its_piling_up,
|
LOCATIONS.the_logo, LOCATIONS.to_the_moon, LOCATIONS.its_piling_up,
|
||||||
LOCATIONS.use_it_later, LOCATIONS.efficiency_1, LOCATIONS.preparing_to_launch,
|
LOCATIONS.use_it_later, LOCATIONS.efficiency_1, LOCATIONS.preparing_to_launch,
|
||||||
@@ -172,7 +172,7 @@ achievement_locations: List[str] = [LOCATIONS.my_eyes, LOCATIONS.painter, LOCATI
|
|||||||
LOCATIONS.mam, LOCATIONS.perfectionist, LOCATIONS.next_dimension, LOCATIONS.oops,
|
LOCATIONS.mam, LOCATIONS.perfectionist, LOCATIONS.next_dimension, LOCATIONS.oops,
|
||||||
LOCATIONS.copy_pasta, LOCATIONS.ive_seen_that_before, LOCATIONS.memories,
|
LOCATIONS.copy_pasta, LOCATIONS.ive_seen_that_before, LOCATIONS.memories,
|
||||||
LOCATIONS.i_need_trains, LOCATIONS.a_bit_early, LOCATIONS.gps]
|
LOCATIONS.i_need_trains, LOCATIONS.a_bit_early, LOCATIONS.gps]
|
||||||
shapesanity_locations: List[str] = [LOCATIONS.shapesanity(x) for x in range(1, max_shapesanity+1)]
|
shapesanity_locations: list[str] = [LOCATIONS.shapesanity(x) for x in range(1, max_shapesanity+1)]
|
||||||
|
|
||||||
|
|
||||||
def init_shapesanity_pool() -> None:
|
def init_shapesanity_pool() -> None:
|
||||||
@@ -186,12 +186,12 @@ def init_shapesanity_pool() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def addlevels(maxlevel: int, logictype: str,
|
def addlevels(maxlevel: int, logictype: str,
|
||||||
random_logic_phase_length: List[int]) -> Dict[str, Tuple[str, LocationProgressType]]:
|
random_logic_phase_length: list[int]) -> dict[str, tuple[str, LocationProgressType]]:
|
||||||
"""Returns a dictionary with all level locations based on player options (maxlevel INCLUDED).
|
"""Returns a dictionary with all level locations based on player options (maxlevel INCLUDED).
|
||||||
If shape requirements are not randomized, the logic type is expected to be vanilla."""
|
If shape requirements are not randomized, the logic type is expected to be vanilla."""
|
||||||
|
|
||||||
# Level 1 is always directly accessible
|
# Level 1 is always directly accessible
|
||||||
locations: Dict[str, Tuple[str, LocationProgressType]] \
|
locations: dict[str, tuple[str, LocationProgressType]] \
|
||||||
= {LOCATIONS.level(1): (REGIONS.main, LocationProgressType.PRIORITY),
|
= {LOCATIONS.level(1): (REGIONS.main, LocationProgressType.PRIORITY),
|
||||||
LOCATIONS.level(1, 1): (REGIONS.main, LocationProgressType.PRIORITY)}
|
LOCATIONS.level(1, 1): (REGIONS.main, LocationProgressType.PRIORITY)}
|
||||||
level_regions = [REGIONS.main, REGIONS.levels_1, REGIONS.levels_2, REGIONS.levels_3,
|
level_regions = [REGIONS.main, REGIONS.levels_1, REGIONS.levels_2, REGIONS.levels_3,
|
||||||
@@ -282,11 +282,11 @@ def addlevels(maxlevel: int, logictype: str,
|
|||||||
|
|
||||||
|
|
||||||
def addupgrades(finaltier: int, logictype: str,
|
def addupgrades(finaltier: int, logictype: str,
|
||||||
category_random_logic_amounts: Dict[str, int]) -> Dict[str, Tuple[str, LocationProgressType]]:
|
category_random_logic_amounts: dict[str, int]) -> dict[str, tuple[str, LocationProgressType]]:
|
||||||
"""Returns a dictionary with all upgrade locations based on player options (finaltier INCLUDED).
|
"""Returns a dictionary with all upgrade locations based on player options (finaltier INCLUDED).
|
||||||
If shape requirements are not randomized, give logic type 0."""
|
If shape requirements are not randomized, give logic type 0."""
|
||||||
|
|
||||||
locations: Dict[str, Tuple[str, LocationProgressType]] = {}
|
locations: dict[str, tuple[str, LocationProgressType]] = {}
|
||||||
upgrade_regions = [REGIONS.main, REGIONS.upgrades_1, REGIONS.upgrades_2, REGIONS.upgrades_3,
|
upgrade_regions = [REGIONS.main, REGIONS.upgrades_1, REGIONS.upgrades_2, REGIONS.upgrades_3,
|
||||||
REGIONS.upgrades_4, REGIONS.upgrades_5]
|
REGIONS.upgrades_4, REGIONS.upgrades_5]
|
||||||
|
|
||||||
@@ -366,13 +366,13 @@ def addupgrades(finaltier: int, logictype: str,
|
|||||||
|
|
||||||
|
|
||||||
def addachievements(excludesoftlock: bool, excludelong: bool, excludeprogressive: bool,
|
def addachievements(excludesoftlock: bool, excludelong: bool, excludeprogressive: bool,
|
||||||
maxlevel: int, upgradelogictype: str, category_random_logic_amounts: Dict[str, int],
|
maxlevel: int, upgradelogictype: str, category_random_logic_amounts: dict[str, int],
|
||||||
goal: str, presentlocations: Dict[str, Tuple[str, LocationProgressType]],
|
goal: str, presentlocations: dict[str, tuple[str, LocationProgressType]],
|
||||||
add_alias: Callable[[str, str], None], has_upgrade_traps: bool
|
add_alias: Callable[[str, str], None], has_upgrade_traps: bool
|
||||||
) -> Dict[str, Tuple[str, LocationProgressType]]:
|
) -> dict[str, tuple[str, LocationProgressType]]:
|
||||||
"""Returns a dictionary with all achievement locations based on player options."""
|
"""Returns a dictionary with all achievement locations based on player options."""
|
||||||
|
|
||||||
locations: Dict[str, Tuple[str, LocationProgressType]] = dict()
|
locations: dict[str, tuple[str, LocationProgressType]] = dict()
|
||||||
upgrade_regions = [REGIONS.main, REGIONS.upgrades_1, REGIONS.upgrades_2, REGIONS.upgrades_3,
|
upgrade_regions = [REGIONS.main, REGIONS.upgrades_1, REGIONS.upgrades_2, REGIONS.upgrades_3,
|
||||||
REGIONS.upgrades_4, REGIONS.upgrades_5]
|
REGIONS.upgrades_4, REGIONS.upgrades_5]
|
||||||
|
|
||||||
@@ -472,10 +472,10 @@ def addachievements(excludesoftlock: bool, excludelong: bool, excludeprogressive
|
|||||||
|
|
||||||
|
|
||||||
def addshapesanity(amount: int, random: Random, append_shapesanity: Callable[[str], None],
|
def addshapesanity(amount: int, random: Random, append_shapesanity: Callable[[str], None],
|
||||||
add_alias: Callable[[str, str], None]) -> Dict[str, Tuple[str, LocationProgressType]]:
|
add_alias: Callable[[str, str], None]) -> dict[str, tuple[str, LocationProgressType]]:
|
||||||
"""Returns a dictionary with a given number of random shapesanity locations."""
|
"""Returns a dictionary with a given number of random shapesanity locations."""
|
||||||
|
|
||||||
included_shapes: Dict[str, Tuple[str, LocationProgressType]] = {}
|
included_shapes: dict[str, tuple[str, LocationProgressType]] = {}
|
||||||
|
|
||||||
def f(name: str, region: str, alias: str, progress: LocationProgressType = LocationProgressType.DEFAULT) -> None:
|
def f(name: str, region: str, alias: str, progress: LocationProgressType = LocationProgressType.DEFAULT) -> None:
|
||||||
included_shapes[name] = (region, progress)
|
included_shapes[name] = (region, progress)
|
||||||
@@ -518,11 +518,11 @@ def addshapesanity(amount: int, random: Random, append_shapesanity: Callable[[st
|
|||||||
return included_shapes
|
return included_shapes
|
||||||
|
|
||||||
|
|
||||||
def addshapesanity_ut(shapesanity_names: List[str], add_alias: Callable[[str, str], None]
|
def addshapesanity_ut(shapesanity_names: list[str], add_alias: Callable[[str, str], None]
|
||||||
) -> Dict[str, Tuple[str, LocationProgressType]]:
|
) -> dict[str, tuple[str, LocationProgressType]]:
|
||||||
"""Returns the same information as addshapesanity but will add specific values based on a UT rebuild."""
|
"""Returns the same information as addshapesanity but will add specific values based on a UT rebuild."""
|
||||||
|
|
||||||
included_shapes: Dict[str, Tuple[str, LocationProgressType]] = {}
|
included_shapes: dict[str, tuple[str, LocationProgressType]] = {}
|
||||||
|
|
||||||
for name in shapesanity_names:
|
for name in shapesanity_names:
|
||||||
for options in [shapesanity_simple, shapesanity_1_4, shapesanity_two_sided, shapesanity_three_parts,
|
for options in [shapesanity_simple, shapesanity_1_4, shapesanity_two_sided, shapesanity_three_parts,
|
||||||
@@ -540,7 +540,7 @@ def addshapesanity_ut(shapesanity_names: List[str], add_alias: Callable[[str, st
|
|||||||
class ShapezLocation(Location):
|
class ShapezLocation(Location):
|
||||||
game = OTHER.game_name
|
game = OTHER.game_name
|
||||||
|
|
||||||
def __init__(self, player: int, name: str, address: Optional[int], region: Region,
|
def __init__(self, player: int, name: str, address: int | None, region: Region,
|
||||||
progress_type: LocationProgressType):
|
progress_type: LocationProgressType):
|
||||||
super(ShapezLocation, self).__init__(player, name, address, region)
|
super(ShapezLocation, self).__init__(player, name, address, region)
|
||||||
self.progress_type = progress_type
|
self.progress_type = progress_type
|
||||||
|
@@ -1,5 +1,3 @@
|
|||||||
from typing import Dict, Tuple, List
|
|
||||||
|
|
||||||
from BaseClasses import Region, MultiWorld, LocationProgressType, ItemClassification, CollectionState
|
from BaseClasses import Region, MultiWorld, LocationProgressType, ItemClassification, CollectionState
|
||||||
from .items import ShapezItem
|
from .items import ShapezItem
|
||||||
from .locations import ShapezLocation
|
from .locations import ShapezLocation
|
||||||
@@ -102,7 +100,7 @@ def has_x_belt_multiplier(state: CollectionState, player: int, needed: float) ->
|
|||||||
return multiplier >= needed
|
return multiplier >= needed
|
||||||
|
|
||||||
|
|
||||||
def has_logic_list_building(state: CollectionState, player: int, buildings: List[str], index: int,
|
def has_logic_list_building(state: CollectionState, player: int, buildings: list[str], index: int,
|
||||||
includeuseful: bool) -> bool:
|
includeuseful: bool) -> bool:
|
||||||
|
|
||||||
# Includes balancer, tunnel, and trash in logic in order to make them appear in earlier spheres
|
# Includes balancer, tunnel, and trash in logic in order to make them appear in earlier spheres
|
||||||
@@ -126,11 +124,11 @@ def has_logic_list_building(state: CollectionState, player: int, buildings: List
|
|||||||
|
|
||||||
|
|
||||||
def create_shapez_regions(player: int, multiworld: MultiWorld, floating: bool,
|
def create_shapez_regions(player: int, multiworld: MultiWorld, floating: bool,
|
||||||
included_locations: Dict[str, Tuple[str, LocationProgressType]],
|
included_locations: dict[str, tuple[str, LocationProgressType]],
|
||||||
location_name_to_id: Dict[str, int], level_logic_buildings: List[str],
|
location_name_to_id: dict[str, int], level_logic_buildings: list[str],
|
||||||
upgrade_logic_buildings: List[str], early_useful: str, goal: str) -> List[Region]:
|
upgrade_logic_buildings: list[str], early_useful: str, goal: str) -> list[Region]:
|
||||||
"""Creates and returns a list of all regions with entrances and all locations placed correctly."""
|
"""Creates and returns a list of all regions with entrances and all locations placed correctly."""
|
||||||
regions: Dict[str, Region] = {name: Region(name, player, multiworld) for name in all_regions}
|
regions: dict[str, Region] = {name: Region(name, player, multiworld) for name in all_regions}
|
||||||
|
|
||||||
# Creates ShapezLocations for every included location and puts them into the correct region
|
# Creates ShapezLocations for every included location and puts them into the correct region
|
||||||
for name, data in included_locations.items():
|
for name, data in included_locations.items():
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from test.bases import WorldTestBase
|
from test.bases import WorldTestBase
|
||||||
from .. import options_presets, ShapezWorld
|
from .. import ShapezWorld
|
||||||
from ..data.strings import GOALS, OTHER, ITEMS, LOCATIONS, CATEGORY, OPTIONS, SHAPESANITY
|
from ..data.strings import GOALS, OTHER, ITEMS, LOCATIONS, CATEGORY, OPTIONS, SHAPESANITY
|
||||||
from ..options import max_levels_and_upgrades, max_shapesanity
|
from ..options import max_levels_and_upgrades, max_shapesanity
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user