Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: move option results to the World class instead of MultiWorld #993

Merged
merged 120 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
120 commits
Select commit Hold shift + click to select a range
24471ce
map option objects to a `World.options` dict
alwaysintreble Sep 2, 2022
220571f
convert RoR2 to options dict system for testing
alwaysintreble Sep 2, 2022
643205c
add temp behavior for lttp with notes
alwaysintreble Sep 2, 2022
695c94c
copy/paste bad
alwaysintreble Sep 25, 2022
caaf051
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Sep 25, 2022
d481eed
convert `set_default_common_options` to a namespace property
alwaysintreble Sep 29, 2022
f9a8bb2
reorganize test call order
alwaysintreble Sep 29, 2022
cded105
have fill_restrictive use the new options system
alwaysintreble Sep 29, 2022
be3fa3a
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Oct 18, 2022
52290df
update world api
alwaysintreble Oct 18, 2022
5896e6c
update soe tests
alwaysintreble Oct 18, 2022
cdcd06c
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Oct 29, 2022
2581d57
fix world api
alwaysintreble Oct 29, 2022
121152b
core: auto initialize a dataclass on the World class with the option …
el-u Jan 9, 2023
82ff125
core: auto initialize a dataclass on the World class with the option …
el-u Jan 9, 2023
ad2f59e
Merge pull request #14 from el-u/options_dict
alwaysintreble Jan 9, 2023
43353de
add `as_dict` method to the options dataclass
alwaysintreble Jan 9, 2023
af5647d
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Jan 9, 2023
76833d5
fix namespace issues with tests
alwaysintreble Jan 9, 2023
d85fb69
have current option updates use `.value` instead of changing the option
alwaysintreble Feb 12, 2023
42c1abb
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Feb 12, 2023
cfdc0b1
update ror2 to use the new options system again
alwaysintreble Feb 12, 2023
eaadb6e
revert the junk pool dict since it's cased differently
alwaysintreble Feb 12, 2023
d890de4
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Feb 14, 2023
0658a5b
fix begin_with_loop typo
alwaysintreble Feb 14, 2023
effbca0
write new and old options to spoiler
alwaysintreble Feb 14, 2023
b78b7d3
change factorio option behavior back
alwaysintreble Feb 14, 2023
94d18dc
fix comparisons
alwaysintreble Feb 14, 2023
0c0663b
move common and per_game_common options to new system
alwaysintreble Feb 14, 2023
a638582
core: automatically create missing options_dataclass from legacy opti…
el-u Feb 14, 2023
11214aa
Merge pull request #15 from el-u/options_dict
alwaysintreble Feb 14, 2023
fe679fc
remove spoiler special casing and add back the Factorio option changi…
alwaysintreble Feb 14, 2023
c5684bb
give ArchipIDLE the default options_dataclass so its options get gene…
alwaysintreble Feb 15, 2023
cecd3f7
reimplement `inspect.get_annotations`
alwaysintreble Feb 17, 2023
1fbc1a4
move option info generation for webhost to new system
alwaysintreble Feb 17, 2023
c3ad00b
need to include Common and PerGame common since __annotations__ doesn…
alwaysintreble Feb 17, 2023
1730eaf
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Feb 17, 2023
1b1ee31
use get_type_hints for the options dictionary
alwaysintreble Feb 21, 2023
85e98a0
typing.get_type_hints returns the bases too.
alwaysintreble Feb 21, 2023
a24bb2e
forgot to sweep through generate
alwaysintreble Feb 21, 2023
9df025d
sweep through all the tests
alwaysintreble Feb 21, 2023
337133c
swap to a metaclass property
alwaysintreble Feb 22, 2023
aadbd56
move remaining usages from get_type_hints to metaclass property
el-u Feb 25, 2023
2584535
move remaining usages from __annotations__ to metaclass property
el-u Feb 25, 2023
0ae2acc
move remaining usages from legacy dictionaries to metaclass property
el-u Feb 25, 2023
a147aae
remove legacy dictionaries
el-u Feb 25, 2023
88db4f7
cache the metaclass property
el-u Feb 25, 2023
01374e0
clarify inheritance in world api
el-u Feb 25, 2023
9d4ab5b
Merge pull request #16 from el-u/options_dict
alwaysintreble Feb 25, 2023
069328c
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Mar 6, 2023
b831bac
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Mar 13, 2023
ac123db
move the messenger to new options system
alwaysintreble Mar 13, 2023
e6806ed
add an assert for my dumb
alwaysintreble Mar 13, 2023
7c7a49f
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Mar 14, 2023
2c8afbc
update the doc
alwaysintreble Mar 14, 2023
f8ba777
rename o to options
alwaysintreble Mar 14, 2023
984d659
missed a spot
alwaysintreble Mar 14, 2023
61b82f1
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Apr 1, 2023
e959c49
update new messenger options
alwaysintreble Apr 1, 2023
ec8c75b
comment spacing
alwaysintreble Apr 1, 2023
5f32194
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble May 21, 2023
2b46533
fix tests
alwaysintreble May 21, 2023
e6424e2
fix missing import
alwaysintreble May 21, 2023
f189f5d
make the documentation definition more accurate
alwaysintreble May 25, 2023
73e5875
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble May 31, 2023
2ba7464
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Jun 28, 2023
3e1be1e
use options system for loc creation
alwaysintreble Jun 28, 2023
fc93f97
type cast MessengerWorld
alwaysintreble Jun 28, 2023
0b9959e
fix typo and use quotes for cast
alwaysintreble Jun 28, 2023
996697f
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Jul 19, 2023
266acd2
LTTP: set random seed in tests
alwaysintreble Jul 19, 2023
c39081a
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Jul 23, 2023
4596be9
ArchipIdle: remove change here as it's default on AutoWorld
alwaysintreble Jul 23, 2023
41ed545
Stardew: Need to set state because `set_default_common_options` used to
alwaysintreble Jul 23, 2023
26976b8
The Messenger: update shop rando and helpers to new system; optimize …
alwaysintreble Jul 23, 2023
7a114d4
Add a kwarg to `as_dict` to do the casing for you
alwaysintreble Jul 23, 2023
bb06b3a
RoR2: use new kwarg for less code
alwaysintreble Jul 23, 2023
8c8adbf
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Sep 1, 2023
f5da39e
RoR2: revert some accidental reverts
alwaysintreble Sep 2, 2023
9cf454b
The Messenger: remove an unnecessary variable
alwaysintreble Sep 2, 2023
37f6d8b
remove TypeVar that isn't used
beauxq Sep 2, 2023
d381d1d
CommonOptions not abstract
beauxq Sep 2, 2023
6d418f9
Docs: fix mistake in options api.md
alwaysintreble Sep 2, 2023
c02be73
remove unused TypeVar
alwaysintreble Sep 2, 2023
2e30f07
create options for item link worlds
alwaysintreble Sep 3, 2023
8583c2a
revert accidental doc removals
alwaysintreble Sep 3, 2023
c58f4a5
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Sep 26, 2023
c3a666f
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Sep 27, 2023
833f09c
Item Links: set default options on group
alwaysintreble Sep 27, 2023
06ba9ba
change Zillion to new options dataclass
beauxq Sep 28, 2023
7d09402
remove unused parameter to function
beauxq Sep 28, 2023
ddb630b
use TypeGuard for Literal narrowing
beauxq Oct 1, 2023
de98a33
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Oct 3, 2023
cf0e267
Merge remote-tracking branch 'Main/main' into options_dict
alwaysintreble Oct 6, 2023
dc041df
Merge branch 'main' into options_dict
black-sliver Oct 7, 2023
366a069
Merge branch 'options_dict' into treble/options_dict
beauxq Oct 7, 2023
668d598
move dlc quest to new api
alwaysintreble Oct 7, 2023
b952aaa
move overcooked 2 to new api
alwaysintreble Oct 7, 2023
555ac4c
Merge remote-tracking branch 'TrebleAP/options_dict' into options_dict
alwaysintreble Oct 7, 2023
75e2c6a
Zillion: move to new options dataclass
alwaysintreble Oct 7, 2023
8a5c157
fixed some missed code in oc2
alwaysintreble Oct 7, 2023
4a9e222
Merge remote-tracking branch 'TrebleAP/options_dict' into options_dict
alwaysintreble Oct 7, 2023
bcec62e
- Tried to be compliant with 993 (WIP?)
agilbert1412 Oct 7, 2023
0c1b3b2
- I think it all works now
agilbert1412 Oct 8, 2023
db38f11
- Removed last trace of me touching core
agilbert1412 Oct 8, 2023
5eb17a1
typo
alwaysintreble Oct 8, 2023
16ae3ad
It now passes all tests!
agilbert1412 Oct 8, 2023
228dfaa
Improve options, fix all issues I hope
agilbert1412 Oct 9, 2023
92f08a7
- Fixed init options
agilbert1412 Oct 9, 2023
095195a
dlcquest: fix bad imports
alwaysintreble Oct 9, 2023
f5c0e23
missed a file
alwaysintreble Oct 9, 2023
c38cce9
- Reduce code duplication
agilbert1412 Oct 9, 2023
4876639
add as_dict documentation
alwaysintreble Oct 9, 2023
b0f7671
- Use .items(), get option name more directly, fix slot data content
agilbert1412 Oct 10, 2023
82ae9df
- Remove generic options from the slot data
agilbert1412 Oct 10, 2023
db21617
Make Stardew Valley compliant
alwaysintreble Oct 10, 2023
86e956b
resolve conflicts
alwaysintreble Oct 10, 2023
130da25
improve slot data documentation
alwaysintreble Oct 10, 2023
d8fab8e
remove `CommonOptions.get_value` (#21)
beauxq Oct 10, 2023
1e707c7
better slot data description
alwaysintreble Oct 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions BaseClasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,18 +196,28 @@ def set_seed(self, seed: Optional[int] = None, secure: bool = False, name: Optio
range(1, self.players + 1)}

def set_options(self, args):
for option_key in Options.common_options:
setattr(self, option_key, getattr(args, option_key, {}))
for option_key in Options.per_game_common_options:
setattr(self, option_key, getattr(args, option_key, {}))

for player in self.player_ids:
self.custom_data[player] = {}
world_type = AutoWorld.AutoWorldRegister.world_types[self.game[player]]
self.worlds[player] = world_type(self, player)
for option_key in Options.common_options:
option_values = getattr(args, option_key, {})
setattr(self, option_key, option_values)
if player in option_values:
self.worlds[player].options[option_key] = option_values[player]

for option_key in Options.per_game_common_options:
option_values = getattr(args, option_key, {})
setattr(self, option_key, option_values)
if player in option_values:
self.worlds[player].options[option_key] = option_values[player]

for option_key in world_type.option_definitions:
setattr(self, option_key, getattr(args, option_key, {}))
black-sliver marked this conversation as resolved.
Show resolved Hide resolved
option_values = getattr(args, option_key, {}) # TODO remove {} after old lttp options
setattr(self, option_key, option_values) # TODO rip out around 0.4.0
if player in option_values: # TODO more lttp jank
self.worlds[player].options[option_key] = option_values[player]

self.worlds[player] = world_type(self, player)

def set_item_links(self):
item_links = {}
Expand Down
1 change: 1 addition & 0 deletions worlds/AutoWorld.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class World(metaclass=AutoWorldRegister):
A Game should have its own subclass of World in which it defines the required data structures."""

option_definitions: Dict[str, Option[Any]] = {} # link your Options mapping
options: Dict[str, Option[Any]] = {} # option names to resulting option object
black-sliver marked this conversation as resolved.
Show resolved Hide resolved
game: str # name the game
topology_present: bool = False # indicate if world type has any meaningful layout/pathing

Expand Down
81 changes: 40 additions & 41 deletions worlds/ror2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,17 @@ class RiskOfRainWorld(World):

def generate_early(self) -> None:
# figure out how many revivals should exist in the pool
self.total_revivals = int(self.world.total_revivals[self.player].value / 100 *
self.world.total_locations[self.player].value)
self.total_revivals = int(self.options["total_revivals"].value // 100 * self.options["total_locations"].value)

def generate_basic(self) -> None:
# shortcut for starting_inventory... The start_with_revive option lets you start with a Dio's Best Friend
if self.world.start_with_revive[self.player].value:
if self.options["start_with_revive"].value:
self.world.push_precollected(self.world.create_item("Dio's Best Friend", self.player))

# if presets are enabled generate junk_pool from the selected preset
pool_option = self.world.item_weights[self.player].value
pool_option = self.options["item_weights"].value
junk_pool: Dict[str, int] = {}
if self.world.item_pool_presets[self.player]:
if self.options["item_pool_presets"]:
# generate chaos weights if the preset is chosen
if pool_option == ItemWeights.option_chaos:
for name, max_value in item_pool_weights[pool_option].items():
Expand All @@ -62,20 +61,20 @@ def generate_basic(self) -> None:
junk_pool = item_pool_weights[pool_option].copy()
else: # generate junk pool from user created presets
junk_pool = {
"Item Scrap, Green": self.world.green_scrap[self.player].value,
"Item Scrap, Red": self.world.red_scrap[self.player].value,
"Item Scrap, Yellow": self.world.yellow_scrap[self.player].value,
"Item Scrap, White": self.world.white_scrap[self.player].value,
"Common Item": self.world.common_item[self.player].value,
"Uncommon Item": self.world.uncommon_item[self.player].value,
"Legendary Item": self.world.legendary_item[self.player].value,
"Boss Item": self.world.boss_item[self.player].value,
"Lunar Item": self.world.lunar_item[self.player].value,
"Equipment": self.world.equipment[self.player].value
"Item Scrap, Green": self.options["green_scrap"].value,
"Item Scrap, Red": self.options["red_scrap"].value,
"Item Scrap, Yellow": self.options["yellow_scrap"].value,
"Item Scrap, White": self.options["white_scrap"].value,
"Common Item": self.options["common_item"].value,
"Uncommon Item": self.options["uncommon_item"].value,
"Legendary Item": self.options["legendary_item"].value,
"Boss Item": self.options["boss_item"].value,
"Lunar Item": self.options["lunar_item"].value,
"Equipment": self.options["equipment"].value
}

# remove lunar items from the pool if they're disabled in the yaml unless lunartic is rolled
if not (self.world.enable_lunar[self.player] or pool_option == ItemWeights.option_lunartic):
if not (self.options["enable_lunar"] or pool_option == ItemWeights.option_lunartic):
junk_pool.pop("Lunar Item")

# Generate item pool
Expand All @@ -85,7 +84,7 @@ def generate_basic(self) -> None:

# Fill remaining items with randomly generated junk
itempool += self.world.random.choices(list(junk_pool.keys()), weights=list(junk_pool.values()),
k=self.world.total_locations[self.player].value - self.total_revivals)
k=self.options["total_locations"].value - self.total_revivals)

# Convert itempool into real items
itempool = list(map(lambda name: self.create_item(name), itempool))
Expand All @@ -98,24 +97,24 @@ def set_rules(self) -> None:
def create_regions(self) -> None:
menu = create_region(self.world, self.player, "Menu")
petrichor = create_region(self.world, self.player, "Petrichor V",
[f"ItemPickup{i + 1}" for i in range(self.world.total_locations[self.player].value)])
[f"ItemPickup{i + 1}" for i in range(self.options["total_locations"].value)])

connection = Entrance(self.player, "Lobby", menu)
menu.exits.append(connection)
connection.connect(petrichor)

self.world.regions += [menu, petrichor]

create_events(self.world, self.player)
self.create_events()

def fill_slot_data(self):
return {
"itemPickupStep": self.world.item_pickup_step[self.player].value,
"itemPickupStep": self.options["item_pickup_step"].value,
"seed": "".join(self.world.slot_seeds[self.player].choice(string.digits) for _ in range(16)),
"totalLocations": self.world.total_locations[self.player].value,
"totalRevivals": self.world.total_revivals[self.player].value,
"startWithDio": self.world.start_with_revive[self.player].value,
"FinalStageDeath": self.world.final_stage_death[self.player].value
"totalLocations": self.options["total_locations"].value,
"totalRevivals": self.options["total_revivals"].value,
"startWithDio": self.options["start_with_revive"].value,
"FinalStageDeath": self.options["final_stage_death"].value
}

def create_item(self, name: str) -> Item:
Expand All @@ -129,23 +128,23 @@ def create_item(self, name: str) -> Item:
item = RiskOfRainItem(name, classification, item_id, self.player)
return item


def create_events(world: MultiWorld, player: int) -> None:
total_locations = world.total_locations[player].value
num_of_events = total_locations // 25
if total_locations / 25 == num_of_events:
num_of_events -= 1
world_region = world.get_region("Petrichor V", player)

for i in range(num_of_events):
event_loc = RiskOfRainLocation(player, f"Pickup{(i + 1) * 25}", None, world_region)
event_loc.place_locked_item(RiskOfRainItem(f"Pickup{(i + 1) * 25}", ItemClassification.progression, None, player))
event_loc.access_rule(lambda state, i=i: state.can_reach(f"ItemPickup{((i + 1) * 25) - 1}", player))
world_region.locations.append(event_loc)

victory_event = RiskOfRainLocation(player, "Victory", None, world_region)
victory_event.place_locked_item(RiskOfRainItem("Victory", ItemClassification.progression, None, player))
world_region.locations.append(victory_event)
def create_events(self) -> None:
total_locations = self.options["total_locations"].value
num_of_events = total_locations // 25
if total_locations / 25 == num_of_events:
num_of_events -= 1
world_region = self.world.get_region("Petrichor V", self.player)

for i in range(num_of_events):
event_loc = RiskOfRainLocation(self.player, f"Pickup{(i + 1) * 25}", None, world_region)
event_loc.place_locked_item(RiskOfRainItem(f"Pickup{(i + 1) * 25}",
ItemClassification.progression, None, self.player))
event_loc.access_rule(lambda state, i=i: state.can_reach(f"ItemPickup{((i + 1) * 25) - 1}", self.player))
world_region.locations.append(event_loc)

victory_event = RiskOfRainLocation(self.player, "Victory", None, world_region)
victory_event.place_locked_item(RiskOfRainItem("Victory", ItemClassification.progression, None, self.player))
world_region.locations.append(victory_event)


def create_region(world: MultiWorld, player: int, name: str, locations: List[str] = None) -> Region:
Expand Down