Skip to content

Commit a6b15fc

Browse files
Jouramieagilbert1412
authored andcommitted
Stardew Valley: implement new game (ArchipelagoMW#1455)
* Stardew Valley Archipelago implementation * fix breaking changes * - Added and Updated Documentation for the game * Removed fun * Remove entire idea of step, due to possible inconsistency with the main AP core * Commented out the desired steps, fix renaming after rebase * Fixed wording * tests now passes on 3.8 * run flake8 * remove dependency so apworld work again * remove dependency for real * - Fix Formatting in the Game Page - Removed disabled Option Descriptions for Entrance Randomizer - Improved Game Page's description of the Arcade Machine buffs - Trimmed down the text on the Options page for Arcade Machines, so that it is smaller * - Removed blankspace * remove player field * remove None check in options * document the scripts * fix pytest warning * use importlib.resources.files * fix * add version requirement to importlib_resources * remove __init__.py from data folder * increment data version * let the __init__.py for 3.9 * use sorted() instead of list() * replace frozenset from fish_data with tuples * remove dependency on pytest * - Add a bit of text to the guide to tell them about how to redeem some received items * - Added a comment about which mod version to use * change single quotes for double quotes * Minimum client version both ways * Changed version number to be more specific. The mod will handle deciding --------- Co-authored-by: Alex Gilbert <[email protected]>
1 parent c4d6b1e commit a6b15fc

34 files changed

+5334
-1
lines changed

setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"Rogue Legacy",
4646
"Donkey Kong Country 3",
4747
"Super Mario World",
48+
"Stardew Valley",
4849
"Timespinner",
4950
}
5051

test/TestBase.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
import pathlib
12
import typing
23
import unittest
3-
import pathlib
44
from argparse import Namespace
55

66
import Utils

worlds/stardew_valley/__init__.py

+188
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
from typing import Dict, Any, Iterable, Optional, Union
2+
3+
from BaseClasses import Region, Entrance, Location, Item, Tutorial
4+
from worlds.AutoWorld import World, WebWorld
5+
from . import rules, logic, options
6+
from .bundles import get_all_bundles, Bundle
7+
from .items import item_table, create_items, ItemData, Group
8+
from .locations import location_table, create_locations, LocationData
9+
from .logic import StardewLogic, StardewRule, _True, _And
10+
from .options import stardew_valley_options, StardewOptions, fetch_options
11+
from .regions import create_regions
12+
from .rules import set_rules
13+
14+
client_version = 0
15+
16+
17+
class StardewLocation(Location):
18+
game: str = "Stardew Valley"
19+
20+
def __init__(self, player: int, name: str, address: Optional[int], parent=None):
21+
super().__init__(player, name, address, parent)
22+
self.event = not address
23+
24+
25+
class StardewItem(Item):
26+
game: str = "Stardew Valley"
27+
28+
29+
class StardewWebWorld(WebWorld):
30+
theme = "dirt"
31+
bug_report_page = "https://github.com/agilbert1412/StardewArchipelago/issues/new?labels=bug&title=%5BBug%5D%3A+Brief+Description+of+bug+here"
32+
33+
tutorials = [Tutorial(
34+
"Multiworld Setup Guide",
35+
"A guide to playing Stardew Valley with Archipelago.",
36+
"English",
37+
"setup_en.md",
38+
"setup/en",
39+
["KaitoKid", "Jouramie"]
40+
)]
41+
42+
43+
class StardewValleyWorld(World):
44+
"""
45+
Stardew Valley farming simulator game where the objective is basically to spend the least possible time on your farm.
46+
"""
47+
game = "Stardew Valley"
48+
option_definitions = stardew_valley_options
49+
topology_present = False
50+
51+
item_name_to_id = {name: data.code for name, data in item_table.items()}
52+
location_name_to_id = {name: data.code for name, data in location_table.items()}
53+
54+
data_version = 1
55+
required_client_version = (0, 3, 9)
56+
57+
options: StardewOptions
58+
logic: StardewLogic
59+
60+
web = StardewWebWorld()
61+
modified_bundles: Dict[str, Bundle]
62+
randomized_entrances: Dict[str, str]
63+
64+
def generate_early(self):
65+
self.options = fetch_options(self.multiworld, self.player)
66+
self.logic = StardewLogic(self.player, self.options)
67+
self.modified_bundles = get_all_bundles(self.multiworld.random,
68+
self.logic,
69+
self.options[options.BundleRandomization],
70+
self.options[options.BundlePrice])
71+
72+
def create_regions(self):
73+
def create_region(name: str, exits: Iterable[str]) -> Region:
74+
region = Region(name, self.player, self.multiworld)
75+
region.exits = [Entrance(self.player, exit_name, region) for exit_name in exits]
76+
return region
77+
78+
world_regions, self.randomized_entrances = create_regions(create_region, self.multiworld.random, self.options)
79+
self.multiworld.regions.extend(world_regions)
80+
81+
def add_location(name: str, code: Optional[int], region: str):
82+
region = self.multiworld.get_region(region, self.player)
83+
location = StardewLocation(self.player, name, code, region)
84+
location.access_rule = lambda _: True
85+
region.locations.append(location)
86+
87+
create_locations(add_location, self.options, self.multiworld.random)
88+
89+
def create_items(self):
90+
locations_count = len([location
91+
for location in self.multiworld.get_locations(self.player)
92+
if not location.event])
93+
items_to_exclude = [excluded_items
94+
for excluded_items in self.multiworld.precollected_items[self.player]
95+
if not item_table[excluded_items.name].has_any_group(Group.RESOURCE_PACK,
96+
Group.FRIENDSHIP_PACK)]
97+
created_items = create_items(self.create_item, locations_count + len(items_to_exclude), self.options,
98+
self.multiworld.random)
99+
self.multiworld.itempool += created_items
100+
101+
for item in items_to_exclude:
102+
self.multiworld.itempool.remove(item)
103+
104+
self.setup_season_events()
105+
self.setup_victory()
106+
107+
def set_rules(self):
108+
set_rules(self.multiworld, self.player, self.options, self.logic, self.modified_bundles)
109+
110+
def create_item(self, item: Union[str, ItemData]) -> StardewItem:
111+
if isinstance(item, str):
112+
item = item_table[item]
113+
114+
return StardewItem(item.name, item.classification, item.code, self.player)
115+
116+
def setup_season_events(self):
117+
self.multiworld.push_precollected(self.create_item("Spring"))
118+
self.create_event_location(location_table["Summer"], self.logic.received("Spring"), "Summer")
119+
self.create_event_location(location_table["Fall"], self.logic.received("Summer"), "Fall")
120+
self.create_event_location(location_table["Winter"], self.logic.received("Fall"), "Winter")
121+
self.create_event_location(location_table["Year Two"], self.logic.received("Winter"), "Year Two")
122+
123+
def setup_victory(self):
124+
if self.options[options.Goal] == options.Goal.option_community_center:
125+
self.create_event_location(location_table["Complete Community Center"],
126+
self.logic.can_complete_community_center().simplify(),
127+
"Victory")
128+
elif self.options[options.Goal] == options.Goal.option_grandpa_evaluation:
129+
self.create_event_location(location_table["Succeed Grandpa's Evaluation"],
130+
self.logic.can_finish_grandpa_evaluation().simplify(),
131+
"Victory")
132+
elif self.options[options.Goal] == options.Goal.option_bottom_of_the_mines:
133+
self.create_event_location(location_table["Reach the Bottom of The Mines"],
134+
self.logic.can_mine_to_floor(120).simplify(),
135+
"Victory")
136+
elif self.options[options.Goal] == options.Goal.option_cryptic_note:
137+
self.create_event_location(location_table["Complete Quest Cryptic Note"],
138+
self.logic.can_complete_quest("Cryptic Note").simplify(),
139+
"Victory")
140+
elif self.options[options.Goal] == options.Goal.option_master_angler:
141+
self.create_event_location(location_table["Catch Every Fish"],
142+
self.logic.can_catch_every_fish().simplify(),
143+
"Victory")
144+
145+
self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player)
146+
147+
def create_event_location(self, location_data: LocationData, rule: StardewRule, item: str):
148+
region = self.multiworld.get_region(location_data.region, self.player)
149+
location = StardewLocation(self.player, location_data.name, None, region)
150+
location.access_rule = rule
151+
region.locations.append(location)
152+
location.place_locked_item(self.create_item(item))
153+
154+
def get_filler_item_name(self) -> str:
155+
return "Joja Cola"
156+
157+
def fill_slot_data(self) -> Dict[str, Any]:
158+
159+
modified_bundles = {}
160+
for bundle_key in self.modified_bundles:
161+
key, value = self.modified_bundles[bundle_key].to_pair()
162+
modified_bundles[key] = value
163+
164+
return {
165+
"starting_money": self.options[options.StartingMoney],
166+
"entrance_randomization": self.options[options.EntranceRandomization],
167+
"backpack_progression": self.options[options.BackpackProgression],
168+
"tool_progression": self.options[options.ToolProgression],
169+
"elevator_progression": self.options[options.TheMinesElevatorsProgression],
170+
"skill_progression": self.options[options.SkillProgression],
171+
"building_progression": self.options[options.BuildingProgression],
172+
"arcade_machine_progression": self.options[options.ArcadeMachineLocations],
173+
"help_wanted_locations": self.options[options.HelpWantedLocations],
174+
"fishsanity": self.options[options.Fishsanity],
175+
"death_link": self.options["death_link"],
176+
"goal": self.options[options.Goal],
177+
"seed": self.multiworld.per_slot_randoms[self.player].randrange(1000000000), # Seed should be max 9 digits
178+
"multiple_day_sleep_enabled": self.options[options.MultipleDaySleepEnabled],
179+
"multiple_day_sleep_cost": self.options[options.MultipleDaySleepCost],
180+
"experience_multiplier": self.options[options.ExperienceMultiplier],
181+
"debris_multiplier": self.options[options.DebrisMultiplier],
182+
"quick_start": self.options[options.QuickStart],
183+
"gifting": self.options[options.Gifting],
184+
"gift_tax": self.options[options.GiftTax],
185+
"modified_bundles": modified_bundles,
186+
"randomized_entrances": self.randomized_entrances,
187+
"client_version": "2.2.2",
188+
}

0 commit comments

Comments
 (0)