Archipelago/worlds/stardew_valley/__init__.py

189 lines
8.9 KiB
Python

from typing import Dict, Any, Iterable, Optional, Union
from BaseClasses import Region, Entrance, Location, Item, Tutorial
from worlds.AutoWorld import World, WebWorld
from . import rules, logic, options
from .bundles import get_all_bundles, Bundle
from .items import item_table, create_items, ItemData, Group
from .locations import location_table, create_locations, LocationData
from .logic import StardewLogic, StardewRule, _True, _And
from .options import stardew_valley_options, StardewOptions, fetch_options
from .regions import create_regions
from .rules import set_rules
client_version = 0
class StardewLocation(Location):
game: str = "Stardew Valley"
def __init__(self, player: int, name: str, address: Optional[int], parent=None):
super().__init__(player, name, address, parent)
self.event = not address
class StardewItem(Item):
game: str = "Stardew Valley"
class StardewWebWorld(WebWorld):
theme = "dirt"
bug_report_page = "https://github.com/agilbert1412/StardewArchipelago/issues/new?labels=bug&title=%5BBug%5D%3A+Brief+Description+of+bug+here"
tutorials = [Tutorial(
"Multiworld Setup Guide",
"A guide to playing Stardew Valley with Archipelago.",
"English",
"setup_en.md",
"setup/en",
["KaitoKid", "Jouramie"]
)]
class StardewValleyWorld(World):
"""
Stardew Valley farming simulator game where the objective is basically to spend the least possible time on your farm.
"""
game = "Stardew Valley"
option_definitions = stardew_valley_options
topology_present = False
item_name_to_id = {name: data.code for name, data in item_table.items()}
location_name_to_id = {name: data.code for name, data in location_table.items()}
data_version = 1
required_client_version = (0, 3, 9)
options: StardewOptions
logic: StardewLogic
web = StardewWebWorld()
modified_bundles: Dict[str, Bundle]
randomized_entrances: Dict[str, str]
def generate_early(self):
self.options = fetch_options(self.multiworld, self.player)
self.logic = StardewLogic(self.player, self.options)
self.modified_bundles = get_all_bundles(self.multiworld.random,
self.logic,
self.options[options.BundleRandomization],
self.options[options.BundlePrice])
def create_regions(self):
def create_region(name: str, exits: Iterable[str]) -> Region:
region = Region(name, self.player, self.multiworld)
region.exits = [Entrance(self.player, exit_name, region) for exit_name in exits]
return region
world_regions, self.randomized_entrances = create_regions(create_region, self.multiworld.random, self.options)
self.multiworld.regions.extend(world_regions)
def add_location(name: str, code: Optional[int], region: str):
region = self.multiworld.get_region(region, self.player)
location = StardewLocation(self.player, name, code, region)
location.access_rule = lambda _: True
region.locations.append(location)
create_locations(add_location, self.options, self.multiworld.random)
def create_items(self):
locations_count = len([location
for location in self.multiworld.get_locations(self.player)
if not location.event])
items_to_exclude = [excluded_items
for excluded_items in self.multiworld.precollected_items[self.player]
if not item_table[excluded_items.name].has_any_group(Group.RESOURCE_PACK,
Group.FRIENDSHIP_PACK)]
created_items = create_items(self.create_item, locations_count + len(items_to_exclude), self.options,
self.multiworld.random)
self.multiworld.itempool += created_items
for item in items_to_exclude:
self.multiworld.itempool.remove(item)
self.setup_season_events()
self.setup_victory()
def set_rules(self):
set_rules(self.multiworld, self.player, self.options, self.logic, self.modified_bundles)
def create_item(self, item: Union[str, ItemData]) -> StardewItem:
if isinstance(item, str):
item = item_table[item]
return StardewItem(item.name, item.classification, item.code, self.player)
def setup_season_events(self):
self.multiworld.push_precollected(self.create_item("Spring"))
self.create_event_location(location_table["Summer"], self.logic.received("Spring"), "Summer")
self.create_event_location(location_table["Fall"], self.logic.received("Summer"), "Fall")
self.create_event_location(location_table["Winter"], self.logic.received("Fall"), "Winter")
self.create_event_location(location_table["Year Two"], self.logic.received("Winter"), "Year Two")
def setup_victory(self):
if self.options[options.Goal] == options.Goal.option_community_center:
self.create_event_location(location_table["Complete Community Center"],
self.logic.can_complete_community_center().simplify(),
"Victory")
elif self.options[options.Goal] == options.Goal.option_grandpa_evaluation:
self.create_event_location(location_table["Succeed Grandpa's Evaluation"],
self.logic.can_finish_grandpa_evaluation().simplify(),
"Victory")
elif self.options[options.Goal] == options.Goal.option_bottom_of_the_mines:
self.create_event_location(location_table["Reach the Bottom of The Mines"],
self.logic.can_mine_to_floor(120).simplify(),
"Victory")
elif self.options[options.Goal] == options.Goal.option_cryptic_note:
self.create_event_location(location_table["Complete Quest Cryptic Note"],
self.logic.can_complete_quest("Cryptic Note").simplify(),
"Victory")
elif self.options[options.Goal] == options.Goal.option_master_angler:
self.create_event_location(location_table["Catch Every Fish"],
self.logic.can_catch_every_fish().simplify(),
"Victory")
self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player)
def create_event_location(self, location_data: LocationData, rule: StardewRule, item: str):
region = self.multiworld.get_region(location_data.region, self.player)
location = StardewLocation(self.player, location_data.name, None, region)
location.access_rule = rule
region.locations.append(location)
location.place_locked_item(self.create_item(item))
def get_filler_item_name(self) -> str:
return "Joja Cola"
def fill_slot_data(self) -> Dict[str, Any]:
modified_bundles = {}
for bundle_key in self.modified_bundles:
key, value = self.modified_bundles[bundle_key].to_pair()
modified_bundles[key] = value
return {
"starting_money": self.options[options.StartingMoney],
"entrance_randomization": self.options[options.EntranceRandomization],
"backpack_progression": self.options[options.BackpackProgression],
"tool_progression": self.options[options.ToolProgression],
"elevator_progression": self.options[options.TheMinesElevatorsProgression],
"skill_progression": self.options[options.SkillProgression],
"building_progression": self.options[options.BuildingProgression],
"arcade_machine_progression": self.options[options.ArcadeMachineLocations],
"help_wanted_locations": self.options[options.HelpWantedLocations],
"fishsanity": self.options[options.Fishsanity],
"death_link": self.options["death_link"],
"goal": self.options[options.Goal],
"seed": self.multiworld.per_slot_randoms[self.player].randrange(1000000000), # Seed should be max 9 digits
"multiple_day_sleep_enabled": self.options[options.MultipleDaySleepEnabled],
"multiple_day_sleep_cost": self.options[options.MultipleDaySleepCost],
"experience_multiplier": self.options[options.ExperienceMultiplier],
"debris_multiplier": self.options[options.DebrisMultiplier],
"quick_start": self.options[options.QuickStart],
"gifting": self.options[options.Gifting],
"gift_tax": self.options[options.GiftTax],
"modified_bundles": modified_bundles,
"randomized_entrances": self.randomized_entrances,
"client_version": "2.2.2",
}