about summary refs log tree commit diff stats
path: root/data
ModeNameSize
-rw-r--r--LL1.yaml61852log stats plain blame
9' href='#n19'>19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
from enum import Enum
from typing import TYPE_CHECKING

from BaseClasses import Location, Item, Region, CollectionState, Entrance
from .items import Lingo2Item
from .rules import AccessRequirements

if TYPE_CHECKING:
    from . import Lingo2World


class LetterPlacementType(Enum):
    ANY = 0
    DISALLOW = 1
    FORCE = 2


def get_required_regions(reqs: AccessRequirements, world: "Lingo2World",
                         regions: dict[str, Region] | None) -> list[Region]:
    # Replace required rooms with regions for the top level requirement, which saves looking up the regions during rule
    # checking.
    if regions is not None:
        return [regions[room_name] for room_name in reqs.rooms]
    else:
        return [world.multiworld.get_region(room_name, world.player) for room_name in reqs.rooms]


class Lingo2Location(Location):
    game: str = "Lingo 2"

    reqs: AccessRequirements | None
    world: "Lingo2World"
    required_regions: list[Region]

    port_id: int
    goal: bool
    letter_placement_type: LetterPlacementType

    @classmethod
    def non_event_location(cls, world: "Lingo2World", code: int, region: Region):
        result = cls(world.player, world.static_logic.location_id_to_name[code], code, region)
        result.reqs = None
        result.world = world
        result.required_regions = []

        return result

    @classmethod
    def event_location(cls, world: "Lingo2World", name: str, region: Region):
        result = cls(world.player, name, None, region)
        result.reqs = None
        result.world = world
        result.required_regions = []

        return result

    def set_access_rule(self, reqs: AccessRequirements, regions: dict[str, Region] | None):
        self.reqs = reqs
        self.required_regions = get_required_regions(reqs, self.world, regions)
        self.access_rule = self._l2_access_rule

    def _l2_access_rule(self, state: CollectionState) -> bool:
        if self.reqs is not None and not self.reqs.check_access(state, self.world):
            return False

        if not all(state.can_reach(region) for region in self.required_regions):
            return False

        return True

    def set_up_letter_rule(self, lpt: LetterPlacementType):
        self.letter_placement_type = lpt
        self.item_rule = self._l2_item_rule

    def _l2_item_rule(self, item: Item) -> bool:
        if not isinstance(item, Lingo2Item):
            return True

        if self.letter_placement_type == LetterPlacementType.FORCE:
            return item.is_letter
        elif self.letter_placement_type == LetterPlacementType.DISALLOW:
            return not item.is_letter

        return True


class Lingo2Entrance(Entrance):
    reqs: AccessRequirements | None
    world: "Lingo2World"
    required_regions: list[Region]

    def __init__(self, world: "Lingo2World", description: str, region: Region):
        super().__init__(world.player, description, region)

        self.reqs = None
        self.world = world
        self.required_regions = []

    def set_access_rule(self, reqs: AccessRequirements, regions: dict[str, Region] | None):
        self.reqs = reqs
        self.required_regions = get_required_regions(reqs, self.world, regions)
        self.access_rule = self._l2_access_rule

    def _l2_access_rule(self, state: CollectionState) -> bool:
        if self.reqs is not None and not self.reqs.check_access(state, self.world):
            return False

        if not all(state.can_reach(region) for region in self.required_regions):
            return False

        return True