Witness: Fix type hints being incompatible with 3.8 (#1991)
* Fixed 3.8 typing in init * Fixed 3.8 typing in items * Fixed 3.8 typing in player logic * Fixed 3.8 typing in static_logic * Fix 3.8 typing in utils * Fixed fault import
This commit is contained in:
parent
1e72851b28
commit
6797216eb8
|
@ -1,7 +1,7 @@
|
|||
"""
|
||||
Archipelago init file for The Witness
|
||||
"""
|
||||
import typing
|
||||
from typing import Dict, Optional
|
||||
|
||||
from BaseClasses import Region, Location, MultiWorld, Item, Entrance, Tutorial
|
||||
from .hints import get_always_hint_locations, get_always_hint_items, get_priority_hint_locations, \
|
||||
|
@ -113,7 +113,7 @@ class WitnessWorld(World):
|
|||
pool_size: int = len(self.locat.CHECK_LOCATION_TABLE) - len(self.locat.EVENT_LOCATION_TABLE) - 1
|
||||
|
||||
# Fill mandatory items and remove precollected and/or starting items from the pool.
|
||||
item_pool: dict[str, int] = self.items.get_mandatory_items()
|
||||
item_pool: Dict[str, int] = self.items.get_mandatory_items()
|
||||
|
||||
for precollected_item_name in [item.name for item in self.multiworld.precollected_items[self.player]]:
|
||||
if precollected_item_name in item_pool:
|
||||
|
@ -250,7 +250,7 @@ class WitnessLocation(Location):
|
|||
game: str = "The Witness"
|
||||
check_hex: int = -1
|
||||
|
||||
def __init__(self, player: int, name: str, address: typing.Optional[int], parent, ch_hex: int = -1):
|
||||
def __init__(self, player: int, name: str, address: Optional[int], parent, ch_hex: int = -1):
|
||||
super().__init__(player, name, address, parent)
|
||||
self.check_hex = ch_hex
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ Defines progression, junk and event items for The Witness
|
|||
"""
|
||||
import copy
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
from typing import Optional, Dict, List
|
||||
|
||||
from BaseClasses import Item, MultiWorld, ItemClassification
|
||||
from .Options import get_option_value, is_option_enabled, the_witness_options
|
||||
|
@ -39,12 +39,12 @@ class StaticWitnessItems:
|
|||
"""
|
||||
Class that handles Witness items independent of world settings
|
||||
"""
|
||||
item_data: dict[str, ItemData] = {}
|
||||
item_groups: dict[str, list[str]] = {}
|
||||
item_data: Dict[str, ItemData] = {}
|
||||
item_groups: Dict[str, List[str]] = {}
|
||||
|
||||
# Useful items that are treated specially at generation time and should not be automatically added to the player's
|
||||
# item list during get_progression_items.
|
||||
special_usefuls: list[str] = ["Puzzle Skip"]
|
||||
special_usefuls: List[str] = ["Puzzle Skip"]
|
||||
|
||||
def __init__(self):
|
||||
for item_name, definition in StaticWitnessLogic.all_items.items():
|
||||
|
@ -76,8 +76,8 @@ class StaticWitnessItems:
|
|||
classification, local_only)
|
||||
|
||||
@staticmethod
|
||||
def get_item_to_door_mappings() -> dict[int, list[int]]:
|
||||
output: dict[int, list[int]] = {}
|
||||
def get_item_to_door_mappings() -> Dict[int, List[int]]:
|
||||
output: Dict[int, List[int]] = {}
|
||||
for item_name, item_data in {name: data for name, data in StaticWitnessItems.item_data.items()
|
||||
if isinstance(data.definition, DoorItemDefinition)}.items():
|
||||
item = StaticWitnessItems.item_data[item_name]
|
||||
|
@ -99,7 +99,7 @@ class WitnessPlayerItems:
|
|||
self._locations: WitnessPlayerLocations = locat
|
||||
|
||||
# Duplicate the static item data, then make any player-specific adjustments to classification.
|
||||
self.item_data: dict[str, ItemData] = copy.copy(StaticWitnessItems.item_data)
|
||||
self.item_data: Dict[str, ItemData] = copy.copy(StaticWitnessItems.item_data)
|
||||
|
||||
# Remove all progression items that aren't actually in the game.
|
||||
self.item_data = {name: data for (name, data) in self.item_data.items()
|
||||
|
@ -119,7 +119,7 @@ class WitnessPlayerItems:
|
|||
item_data.classification = ItemClassification.useful
|
||||
|
||||
# Build the mandatory item list.
|
||||
self._mandatory_items: dict[str, int] = {}
|
||||
self._mandatory_items: Dict[str, int] = {}
|
||||
|
||||
# Add progression items to the mandatory item list.
|
||||
for item_name, item_data in {name: data for (name, data) in self.item_data.items()
|
||||
|
@ -148,20 +148,20 @@ class WitnessPlayerItems:
|
|||
self.item_data[location_name] = ItemData(None, ItemDefinition(0, ItemCategory.EVENT),
|
||||
ItemClassification.progression, False)
|
||||
|
||||
def get_mandatory_items(self) -> dict[str, int]:
|
||||
def get_mandatory_items(self) -> Dict[str, int]:
|
||||
"""
|
||||
Returns the list of items that must be in the pool for the game to successfully generate.
|
||||
"""
|
||||
return self._mandatory_items
|
||||
|
||||
def get_filler_items(self, quantity: int) -> dict[str, int]:
|
||||
def get_filler_items(self, quantity: int) -> Dict[str, int]:
|
||||
"""
|
||||
Generates a list of filler items of the given length.
|
||||
"""
|
||||
if quantity <= 0:
|
||||
return {}
|
||||
|
||||
output: dict[str, int] = {}
|
||||
output: Dict[str, int] = {}
|
||||
remaining_quantity = quantity
|
||||
|
||||
# Add joke items.
|
||||
|
@ -174,7 +174,7 @@ class WitnessPlayerItems:
|
|||
filler_weight = 1 - trap_weight
|
||||
|
||||
# Add filler items to the list.
|
||||
filler_items: dict[str, float]
|
||||
filler_items: Dict[str, float]
|
||||
filler_items = {name: data.definition.weight if isinstance(data.definition, WeightedItemDefinition) else 1
|
||||
for (name, data) in self.item_data.items() if data.definition.category is ItemCategory.FILLER}
|
||||
filler_items = {name: base_weight * filler_weight / sum(filler_items.values())
|
||||
|
@ -188,16 +188,16 @@ class WitnessPlayerItems:
|
|||
for name, base_weight in trap_items.items() if base_weight > 0})
|
||||
|
||||
# Get the actual number of each item by scaling the float weight values to match the target quantity.
|
||||
int_weights: list[int] = build_weighted_int_list(filler_items.values(), remaining_quantity)
|
||||
int_weights: List[int] = build_weighted_int_list(filler_items.values(), remaining_quantity)
|
||||
output.update(zip(filler_items.keys(), int_weights))
|
||||
|
||||
return output
|
||||
|
||||
def get_early_items(self) -> list[str]:
|
||||
def get_early_items(self) -> List[str]:
|
||||
"""
|
||||
Returns items that are ideal for placing on extremely early checks, like the tutorial gate.
|
||||
"""
|
||||
output: list[str] = []
|
||||
output: List[str] = []
|
||||
if "shuffle_symbols" not in the_witness_options.keys() \
|
||||
or is_option_enabled(self._world, self._player_id, "shuffle_symbols"):
|
||||
if get_option_value(self._world, self._player_id, "shuffle_doors") > 0:
|
||||
|
@ -231,25 +231,25 @@ class WitnessPlayerItems:
|
|||
# Sort the output for consistency across versions if the implementation changes but the logic does not.
|
||||
return sorted(output)
|
||||
|
||||
def get_door_ids_in_pool(self) -> list[int]:
|
||||
def get_door_ids_in_pool(self) -> List[int]:
|
||||
"""
|
||||
Returns the total set of all door IDs that are controlled by items in the pool.
|
||||
"""
|
||||
output: list[int] = []
|
||||
output: List[int] = []
|
||||
for item_name, item_data in {name: data for name, data in self.item_data.items()
|
||||
if isinstance(data.definition, DoorItemDefinition)}.items():
|
||||
output += [int(hex_string, 16) for hex_string in item_data.definition.panel_id_hexes]
|
||||
return output
|
||||
|
||||
def get_symbol_ids_not_in_pool(self) -> list[int]:
|
||||
def get_symbol_ids_not_in_pool(self) -> List[int]:
|
||||
"""
|
||||
Returns the item IDs of symbol items that were defined in the configuration file but are not in the pool.
|
||||
"""
|
||||
return [data.ap_code for name, data in StaticWitnessItems.item_data.items()
|
||||
if name not in self.item_data.keys() and data.definition.category is ItemCategory.SYMBOL]
|
||||
|
||||
def get_progressive_item_ids_in_pool(self) -> dict[int, list[int]]:
|
||||
output: dict[int, list[int]] = {}
|
||||
def get_progressive_item_ids_in_pool(self) -> Dict[int, List[int]]:
|
||||
output: Dict[int, List[int]] = {}
|
||||
for item_name, quantity in {name: quantity for name, quantity in self._mandatory_items.items()}.items():
|
||||
item = self.item_data[item_name]
|
||||
if isinstance(item.definition, ProgressiveItemDefinition):
|
||||
|
|
|
@ -16,7 +16,7 @@ When the world has parsed its options, a second function is called to finalize t
|
|||
"""
|
||||
|
||||
import copy
|
||||
from typing import Set, Dict, cast
|
||||
from typing import Set, Dict, cast, List
|
||||
from logging import warning
|
||||
|
||||
from BaseClasses import MultiWorld
|
||||
|
@ -421,7 +421,7 @@ class WitnessPlayerLogic:
|
|||
self.MULTI_LISTS = dict()
|
||||
self.PROG_ITEMS_ACTUALLY_IN_THE_GAME_NO_MULTI = set()
|
||||
self.PROG_ITEMS_ACTUALLY_IN_THE_GAME = set()
|
||||
self.DOOR_ITEMS_BY_ID: dict[str, list[int]] = {}
|
||||
self.DOOR_ITEMS_BY_ID: Dict[str, List[int]] = {}
|
||||
self.STARTING_INVENTORY = set()
|
||||
|
||||
self.DIFFICULTY = get_option_value(world, player, "puzzle_randomization")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Dict, List
|
||||
|
||||
from .utils import define_new_region, parse_lambda, lazy, get_items, get_sigma_normal_logic, get_sigma_expert_logic,\
|
||||
get_vanilla_logic
|
||||
|
@ -16,7 +17,7 @@ class ItemCategory(Enum):
|
|||
EVENT = 7
|
||||
|
||||
|
||||
CATEGORY_NAME_MAPPINGS: dict[str, ItemCategory] = {
|
||||
CATEGORY_NAME_MAPPINGS: Dict[str, ItemCategory] = {
|
||||
"Symbols:": ItemCategory.SYMBOL,
|
||||
"Doors:": ItemCategory.DOOR,
|
||||
"Lasers:": ItemCategory.LASER,
|
||||
|
@ -35,12 +36,12 @@ class ItemDefinition:
|
|||
|
||||
@dataclass(frozen=True)
|
||||
class ProgressiveItemDefinition(ItemDefinition):
|
||||
child_item_names: list[str]
|
||||
child_item_names: List[str]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class DoorItemDefinition(ItemDefinition):
|
||||
panel_id_hexes: list[str]
|
||||
panel_id_hexes: List[str]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
@ -178,8 +179,8 @@ class StaticWitnessLogicObj:
|
|||
|
||||
class StaticWitnessLogic:
|
||||
# Item data parsed from WitnessItems.txt
|
||||
all_items: dict[str, ItemDefinition] = {}
|
||||
_progressive_lookup: dict[str, str] = {}
|
||||
all_items: Dict[str, ItemDefinition] = {}
|
||||
_progressive_lookup: Dict[str, str] = {}
|
||||
|
||||
ALL_REGIONS_BY_NAME = dict()
|
||||
STATIC_CONNECTIONS_BY_REGION_NAME = dict()
|
||||
|
@ -200,7 +201,7 @@ class StaticWitnessLogic:
|
|||
Parses currently defined items from WitnessItems.txt
|
||||
"""
|
||||
|
||||
lines: list[str] = get_items()
|
||||
lines: List[str] = get_items()
|
||||
current_category: ItemCategory = ItemCategory.SYMBOL
|
||||
|
||||
for line in lines:
|
||||
|
@ -217,7 +218,7 @@ class StaticWitnessLogic:
|
|||
|
||||
item_code = int(line_split[0])
|
||||
item_name = line_split[1]
|
||||
arguments: list[str] = line_split[2].split(",") if len(line_split) >= 3 else []
|
||||
arguments: List[str] = line_split[2].split(",") if len(line_split) >= 3 else []
|
||||
|
||||
if current_category in [ItemCategory.DOOR, ItemCategory.LASER]:
|
||||
# Map doors to IDs.
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
from functools import lru_cache
|
||||
from math import floor
|
||||
from typing import *
|
||||
from fractions import Fraction
|
||||
from typing import List, Collection
|
||||
from pkgutil import get_data
|
||||
|
||||
|
||||
def build_weighted_int_list(inputs: Collection[float], total: int) -> list[int]:
|
||||
def build_weighted_int_list(inputs: Collection[float], total: int) -> List[int]:
|
||||
"""
|
||||
Converts a list of floats to a list of ints of a given length, using the Largest Remainder Method.
|
||||
"""
|
||||
|
@ -15,11 +14,11 @@ def build_weighted_int_list(inputs: Collection[float], total: int) -> list[int]:
|
|||
scaled_input = [x * scale_factor for x in inputs]
|
||||
|
||||
# Generate whole number counts, always rounding down.
|
||||
rounded_output: list[int] = [floor(x) for x in scaled_input]
|
||||
rounded_output: List[int] = [floor(x) for x in scaled_input]
|
||||
rounded_sum = sum(rounded_output)
|
||||
|
||||
# If the output's total is insufficient, increment the value that has the largest remainder until we meet our goal.
|
||||
remainders: list[float] = [real - rounded for real, rounded in zip(scaled_input, rounded_output)]
|
||||
remainders: List[float] = [real - rounded for real, rounded in zip(scaled_input, rounded_output)]
|
||||
while rounded_sum < total:
|
||||
max_remainder = max(remainders)
|
||||
if max_remainder == 0:
|
||||
|
|
Loading…
Reference in New Issue