about summary refs log tree commit diff stats
path: root/apworld/regions.py
blob: fe2c99bcd56a24295445e295238fa7d5afc7c67c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight
from typing import TYPE_CHECKING

from BaseClasses import Region, ItemClassification, Entrance
from .items import Lingo2Item
from .locations import Lingo2Location
from .player_logic import AccessRequirements
from .rules import make_location_lambda

if TYPE_CHECKING:
    from . import Lingo2World


def create_region(room, world: "Lingo2World") -> Region:
    new_region = Region(world.static_logic.get_room_region_name(room.id), world.player, world.multiworld)

    for location in world.player_logic.locations_by_room.get(room.id, {}):
        new_location = Lingo2Location(world.player, world.static_logic.location_id_to_name[location.code],
                                      location.code, new_region)
        new_location.access_rule = make_location_lambda(location.reqs, world)
        new_region.locations.append(new_location)

    for event_name, item_name in world.player_logic.event_loc_item_by_room.get(room.id, {}).items():
        new_location = Lingo2Location(world.player, event_name, None, new_region)
        event_item = Lingo2Item(item_name, ItemClassification.progression, None, world.player)
        new_location.place_locked_item(event_item)
        new_region.locations.append(new_location)

    return new_region


def create_regions(world: "Lingo2World"):
    regions = {
        "Menu": Region("Menu", world.player, world.multiworld)
    }

    for room in world.static_logic.objects.rooms:
        region = create_region(room, world)
        regions[region.name] = region

    regions["Menu"].connect(regions["The Entry - Starting Room"], "Start Game")

    # TODO: The requirements of the opposite trigger also matter.
    for connection in world.static_logic.objects.connections:
        from_region = world.static_logic.get_room_region_name(connection.from_room)
        to_region = world.static_logic.get_room_region_name(connection.to_room)
        connection_name = f"{from_region} -> {to_region}"

        reqs = AccessRequirements()

        if connection.HasField("required_door"):
            reqs.merge(world.player_logic.get_door_open_reqs(connection.required_door))

            door = world.static_logic.objects.doors[connection.required_door]
            wmap = world.static_logic.objects.maps[door.map_id]
            connection_name = f"{connection_name} (using {wmap.name} - {door.name})"

        if connection.HasField("port"):
            port = world.static_logic.objects.ports[connection.port]
            connection_name = f"{connection_name} (via port {port.name})"

            if port.HasField("required_door"):
                reqs.merge(world.player_logic.get_door_open_reqs(port.required_door))

        if connection.HasField("painting"):
            painting = world.static_logic.objects.paintings[connection.painting]
            connection_name = f"{connection_name} (via painting {painting.name})"

            if painting.HasField("required_door"):
                reqs.merge(world.player_logic.get_door_open_reqs(painting.required_door))

        if connection.HasField("panel"):
            proxy = connection.panel
            reqs.merge(world.player_logic.get_panel_reqs(proxy.panel,
                                                         proxy.answer if proxy.HasField("answer") else None))

            panel = world.static_logic.objects.panels[proxy.panel]
            if proxy.HasField("answer"):
                connection_name = f"{connection_name} (via panel {panel.name}/{proxy.answer})"
            else:
                connection_name = f"{connection_name} (via panel {panel.name})"

        if from_region in regions and to_region in regions:
            connection = Entrance(world.player, connection_name, regions[from_region])
            connection.access_rule = make_location_lambda(reqs, world)

            regions[from_region].exits.append(connection)
            connection.connect(regions[to_region])

            for region in reqs.rooms:
                world.multiworld.register_indirect_condition(regions[region], connection)

    world.multiworld.regions += regions.values()