-
Notifications
You must be signed in to change notification settings - Fork 705
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SoE: use new AP API and naming and make APworld (#2701)
* SoE: new file naming also fixes test base deprecation * SoE: use options_dataclass * SoE: moar typing * SoE: no more multiworld.random * SoE: replace LogicMixin by SoEPlayerLogic object * SoE: add test that rocket parts always exist * SoE: Even moar typing * SoE: can haz apworld now * SoE: pep up test naming * SoE: use self.options for trap chances * SoE: remove unused import with outdated comment * SoE: move flag and trap extraction to dataclass as suggested by beauxq * SoE: test trap option parsing and item generation
- Loading branch information
1 parent
47dd364
commit e00b5a7
Showing
12 changed files
with
298 additions
and
219 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import typing | ||
from typing import Callable, Set | ||
|
||
from . import pyevermizer | ||
from .options import EnergyCore, OutOfBounds, SequenceBreaks, SoEOptions | ||
|
||
if typing.TYPE_CHECKING: | ||
from BaseClasses import CollectionState | ||
|
||
# TODO: Options may preset certain progress steps (i.e. P_ROCK_SKIP), set in generate_early? | ||
|
||
# TODO: resolve/flatten/expand rules to get rid of recursion below where possible | ||
# Logic.rules are all rules including locations, excluding those with no progress (i.e. locations that only drop items) | ||
rules = [rule for rule in pyevermizer.get_logic() if len(rule.provides) > 0] | ||
# Logic.items are all items and extra items excluding non-progression items and duplicates | ||
item_names: Set[str] = set() | ||
items = [item for item in filter(lambda item: item.progression, pyevermizer.get_items() + pyevermizer.get_extra_items()) | ||
if item.name not in item_names and not item_names.add(item.name)] # type: ignore[func-returns-value] | ||
|
||
|
||
class SoEPlayerLogic: | ||
__slots__ = "player", "out_of_bounds", "sequence_breaks", "has" | ||
player: int | ||
out_of_bounds: bool | ||
sequence_breaks: bool | ||
|
||
has: Callable[..., bool] | ||
""" | ||
Returns True if count of one of evermizer's progress steps is reached based on collected items. i.e. 2 * P_DE | ||
""" | ||
|
||
def __init__(self, player: int, options: "SoEOptions"): | ||
self.player = player | ||
self.out_of_bounds = options.out_of_bounds == OutOfBounds.option_logic | ||
self.sequence_breaks = options.sequence_breaks == SequenceBreaks.option_logic | ||
|
||
if options.energy_core == EnergyCore.option_fragments: | ||
# override logic for energy core fragments | ||
required_fragments = options.required_fragments.value | ||
|
||
def fragmented_has(state: "CollectionState", progress: int, count: int = 1) -> bool: | ||
if progress == pyevermizer.P_ENERGY_CORE: | ||
progress = pyevermizer.P_CORE_FRAGMENT | ||
count = required_fragments | ||
return self._has(state, progress, count) | ||
|
||
self.has = fragmented_has | ||
else: | ||
# default (energy core) logic | ||
self.has = self._has | ||
|
||
def _count(self, state: "CollectionState", progress: int, max_count: int = 0) -> int: | ||
""" | ||
Returns reached count of one of evermizer's progress steps based on collected items. | ||
i.e. returns 0-3 for P_DE based on items providing CHECK_BOSS,DIAMOND_EYE_DROP | ||
""" | ||
n = 0 | ||
for item in items: | ||
for pvd in item.provides: | ||
if pvd[1] == progress: | ||
if state.has(item.name, self.player): | ||
n += state.count(item.name, self.player) * pvd[0] | ||
if n >= max_count > 0: | ||
return n | ||
for rule in rules: | ||
for pvd in rule.provides: | ||
if pvd[1] == progress and pvd[0] > 0: | ||
has = True | ||
for req in rule.requires: | ||
if not self.has(state, req[1], req[0]): | ||
has = False | ||
break | ||
if has: | ||
n += pvd[0] | ||
if n >= max_count > 0: | ||
return n | ||
return n | ||
|
||
def _has(self, state: "CollectionState", progress: int, count: int = 1) -> bool: | ||
"""Default implementation of has""" | ||
if self.out_of_bounds is True and progress == pyevermizer.P_ALLOW_OOB: | ||
return True | ||
if self.sequence_breaks is True and progress == pyevermizer.P_ALLOW_SEQUENCE_BREAKS: | ||
return True | ||
return self._count(state, progress, count) >= count |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.