mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
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
This commit is contained in:
85
worlds/soe/logic.py
Normal file
85
worlds/soe/logic.py
Normal file
@@ -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
|
Reference in New Issue
Block a user