Archipelago/worlds/ror2/Locations.py

120 lines
6.0 KiB
Python

from typing import Tuple
from BaseClasses import Location
from .Options import TotalLocations
from .Options import ChestsPerEnvironment
from .Options import ShrinesPerEnvironment
from .Options import ScavengersPerEnvironment
from .Options import ScannersPerEnvironment
from .Options import AltarsPerEnvironment
from .RoR2Environments import *
class RiskOfRainLocation(Location):
game: str = "Risk of Rain 2"
ror2_locations_start_id = 38000
def get_classic_item_pickups(n: int) -> Dict[str, int]:
"""Get n ItemPickups, capped at the max value for TotalLocations"""
n = max(n, 0)
n = min(n, TotalLocations.range_end)
return { f"ItemPickup{i+1}": ror2_locations_start_id+i for i in range(n) }
item_pickups = get_classic_item_pickups(TotalLocations.range_end)
location_table = item_pickups
def environment_abreviation(long_name:str) -> str:
"""convert long environment names to initials"""
abrev = ""
# go through every word finding a letter (or number) for an initial
for word in long_name.split():
initial = word[0]
for letter in word:
if letter.isalnum():
initial = letter
break
abrev+= initial
return abrev
# highest numbered orderedstages (this is so we can treat the easily caculate the check ids based on the environment and location "offset")
highest_orderedstage: int= max(compress_dict_list_horizontal(environment_orderedstages_table).values())
ror2_locations_start_orderedstage = ror2_locations_start_id + TotalLocations.range_end
class orderedstage_location:
"""A class to behave like a struct for storing the offsets of location types in the allocated space per orderedstage environments."""
# TODO is there a better, more generic way to do this?
offset_ChestsPerEnvironment = 0
offset_ShrinesPerEnvironment = offset_ChestsPerEnvironment + ChestsPerEnvironment.range_end
offset_ScavengersPerEnvironment = offset_ShrinesPerEnvironment + ShrinesPerEnvironment.range_end
offset_ScannersPerEnvironment = offset_ScavengersPerEnvironment + ScavengersPerEnvironment.range_end
offset_AltarsPerEnvironment = offset_ScannersPerEnvironment + ScannersPerEnvironment.range_end
# total space allocated to the locations in a single orderedstage environment
allocation = offset_AltarsPerEnvironment + AltarsPerEnvironment.range_end
def get_environment_locations(chests:int, shrines:int, scavengers:int, scanners:int, altars:int, environment: Tuple[str, int]) -> Dict[str, int]:
"""Get the locations within a specific environment"""
environment_name = environment[0]
environment_index = environment[1]
locations = {}
# due to this mapping, since environment ids are not consecutive, there are lots of "wasted" id numbers
# TODO perhaps a hashing algorithm could be used to compress this range and save "wasted" ids
environment_start_id = environment_index * orderedstage_location.allocation + ror2_locations_start_orderedstage
for n in range(chests):
locations.update({f"{environment_name}: Chest {n+1}": n + orderedstage_location.offset_ChestsPerEnvironment + environment_start_id})
for n in range(shrines):
locations.update({f"{environment_name}: Shrine {n+1}": n + orderedstage_location.offset_ShrinesPerEnvironment + environment_start_id})
for n in range(scavengers):
locations.update({f"{environment_name}: Scavenger {n+1}": n + orderedstage_location.offset_ScavengersPerEnvironment + environment_start_id})
for n in range(scanners):
locations.update({f"{environment_name}: Radio Scanner {n+1}": n + orderedstage_location.offset_ScannersPerEnvironment + environment_start_id})
for n in range(altars):
locations.update({f"{environment_name}: Newt Altar {n+1}": n + orderedstage_location.offset_AltarsPerEnvironment + environment_start_id})
return locations
def get_locations(chests:int, shrines:int, scavengers:int, scanners:int, altars:int, dlc_sotv:bool) -> Dict[str, int]:
"""Get a dictionary of locations for the ordedstage environments with the locations from the parameters."""
locations = {}
orderedstages = compress_dict_list_horizontal(environment_vanilla_orderedstages_table)
if(dlc_sotv): orderedstages.update(compress_dict_list_horizontal(environment_sotv_orderedstages_table))
# for every environment, generate the respective locations
for environment_name, environment_index in orderedstages.items():
# locations = locations | orderedstage_location.get_environment_locations(
locations.update(orderedstage_location.get_environment_locations(
chests=chests,
shrines=shrines,
scavengers=scavengers,
scanners=scanners,
altars=altars,
environment=(environment_name, environment_index)
))
return locations
def getall_locations(dlc_sotv:bool=True) -> Dict[str, int]:
"""
Get all locations in ordered stages.
Set dlc_sotv to true for the SOTV DLC to be included.
"""
# to get all locations, attempt using as many locations as possible
return orderedstage_location.get_locations(
chests=ChestsPerEnvironment.range_end,
shrines=ShrinesPerEnvironment.range_end,
scavengers=ScavengersPerEnvironment.range_end,
scanners=ScannersPerEnvironment.range_end,
altars=AltarsPerEnvironment.range_end,
dlc_sotv=dlc_sotv
)
ror2_location_post_orderedstage = ror2_locations_start_orderedstage + highest_orderedstage*orderedstage_location.allocation
location_table.update(orderedstage_location.getall_locations())
# use the sotv dlc in the lookup table so that all ids can be looked up regardless of use
lookup_id_to_name: Dict[int, str] = {id: name for name, id in location_table.items()}