Beispiel #1
0
def test_replace_node(game_editor):
    # Setup
    world_list = game_editor.game.world_list
    loc = AreaIdentifier("Temple Grounds", "Landing Site")
    loc2 = AreaIdentifier("Temple Grounds", "Service Access")

    landing_site = world_list.area_by_area_location(loc)
    source = landing_site.node_with_name("Save Station")
    door = landing_site.node_with_name("Door to Service Access")
    assert isinstance(door, DockNode)
    req = landing_site.connections[source][door]

    new_node = dataclasses.replace(
        door, identifier=door.identifier.renamed("FooBar"))

    # Run
    game_editor.replace_node(landing_site, door, new_node)

    # Assert
    assert world_list.area_by_area_location(
        loc).connections[source][new_node] is req
    dock_to_landing = world_list.area_by_area_location(loc2).node_with_name(
        "Door to Landing Site")
    assert isinstance(dock_to_landing, DockNode)
    assert dock_to_landing.default_connection.node_name == "FooBar"
Beispiel #2
0
    def _starting_location_on_select_classic(self):
        classics = [
            AreaIdentifier("Mimiga Village", "Start Point"),
            AreaIdentifier("Mimiga Village", "Arthur's House"),
            AreaIdentifier("Labyrinth", "Camp")
        ]

        with self._editor as editor:
            editor.set_configuration_field(
                "starting_location",
                editor.configuration.starting_location.with_elements(
                    classics, self.game_enum))
Beispiel #3
0
def test_add_elevator_connections_to_patches_vanilla(echoes_game_description,
                                                     skip_final_bosses: bool,
                                                     default_echoes_configuration,
                                                     echoes_game_patches):
    # Setup
    patches_factory = echoes_game_description.game.generator.base_patches_factory
    expected = dataclasses.replace(echoes_game_patches,
                                   elevator_connection=echoes_game_description.get_default_elevator_connection())
    if skip_final_bosses:
        node_ident = NodeIdentifier.create("Temple Grounds", "Sky Temple Gateway",
                                           "Teleport to Great Temple - Sky Temple Energy Controller")
        expected.elevator_connection[node_ident] = AreaIdentifier("Temple Grounds", "Credits")

    config = default_echoes_configuration
    config = dataclasses.replace(config,
                                 elevators=dataclasses.replace(config.elevators,
                                                               skip_final_bosses=skip_final_bosses))

    # Run
    result = patches_factory.add_elevator_connections_to_patches(
        config,
        Random(0),
        echoes_game_patches)

    # Assert
    assert result == expected
Beispiel #4
0
def test_create_spawn_point_field(echoes_game_description, empty_patches):
    # Setup
    resource_db = echoes_game_description.resource_database

    loc = AreaIdentifier("Temple Grounds", "Hive Chamber B")
    patches = empty_patches.assign_starting_location(loc).assign_extra_initial_items({
        resource_db.get_by_type_and_index(ResourceType.ITEM, "MorphBall"): 3,
    })

    capacities = [
        {'amount': 3 if item.short_name == "MorphBall" else 0, 'index': item.extra["item_id"]}
        for item in resource_db.item
    ]

    # Run
    result = patch_data_factory._create_spawn_point_field(patches, echoes_game_description)

    # Assert
    assert result == {
        "location": {
            "world_asset_id": 1006255871,
            "area_asset_id": 494654382,
        },
        "amount": capacities,
        "capacity": capacities,
    }
Beispiel #5
0
def test_rename_area(game_editor):
    # Setup
    world_list = game_editor.game.world_list
    loc_1 = AreaIdentifier("Temple Grounds", "Transport to Agon Wastes")
    loc_2 = AreaIdentifier("Agon Wastes", "Transport to Temple Grounds")
    final = AreaIdentifier("Temple Grounds", "Foo Bar Transportation")

    # Run
    game_editor.rename_area(world_list.area_by_area_location(loc_1),
                            "Foo Bar Transportation")

    # Assert
    assert world_list.area_by_area_location(final) is not None
    area_2 = world_list.area_by_area_location(loc_2)
    assert area_2.node_with_name(
        "Elevator to Temple Grounds - Foo Bar Transportation") is not None
def test_create_message_for_hint_relative_area(echoes_game_patches,
                                               blank_pickup, players_config,
                                               echoes_hint_exporter, offset,
                                               distance_text):
    patches = echoes_game_patches.assign_new_pickups([
        (PickupIndex(5), PickupTarget(blank_pickup, 0)),
    ])

    hint = Hint(
        HintType.LOCATION,
        PrecisionPair(HintLocationPrecision.RELATIVE_TO_AREA,
                      HintItemPrecision.DETAILED,
                      include_owner=False,
                      relative=RelativeDataArea(
                          offset, AreaIdentifier("Torvus Bog", "Great Bridge"),
                          HintRelativeAreaName.NAME)), PickupIndex(5))

    namer = EchoesHintNamer({0: patches}, PlayersConfiguration(0, {0: "You"}))
    exporter = HintExporter(namer, random.Random(0), ["A Joke"])

    # Run
    result = exporter.create_message_for_hint(hint, {0: patches},
                                              players_config, True)

    # Assert
    assert result == (
        f'The &push;&main-color=#FF6705B3;Blank Pickup&pop; can be found '
        f'&push;&main-color=#FF3333;{distance_text} {10 + (offset or 0)} rooms&pop; away from '
        f'Torvus Bog - Great Bridge.')
Beispiel #7
0
def test_create_new_dock(skip_qtbot, tmp_path, blank_game_data):
    db_path = Path(tmp_path.joinpath("test-game", "game"))
    game_data = default_data.read_json_then_binary(RandovaniaGame.BLANK)[1]

    window = DataEditorWindow(game_data, db_path, True, True)
    window.set_warning_dialogs_disabled(True)
    skip_qtbot.addWidget(window)

    window.focus_on_area_by_name("Back-Only Lock Room")
    current_area = window.current_area
    target_area = window.game_description.world_list.area_by_area_location(
        AreaIdentifier("Intro", "Explosive Depot"))

    assert current_area.node_with_name("Dock to Explosive Depot") is None
    assert target_area.node_with_name("Dock to Back-Only Lock Room") is None

    # Run
    window._create_new_dock(NodeLocation(0, 0, 0), target_area)

    # Assert
    new_node = current_area.node_with_name("Dock to Explosive Depot")
    assert new_node is not None
    assert window.current_node is new_node

    assert target_area.node_with_name(
        "Dock to Back-Only Lock Room") is not None
Beispiel #8
0
def _area_name_to_area_location(world_list: WorldList,
                                area_name: str) -> AreaIdentifier:
    world_name, area_name = re.match("([^/]+)/([^/]+)", area_name).group(1, 2)

    # Filter out dark world names
    world_name = world_list.world_with_name(world_name).name

    return AreaIdentifier(world_name, area_name)
Beispiel #9
0
def test_one_way_elevator_connections(echoes_game_description, replacement,
                                      expected):
    # Setup
    rng = random.Random(5000)
    target_locations = [AreaIdentifier(f"w{i}", f"a{i}") for i in range(6)]
    elevators = [
        ElevatorHelper(NodeIdentifier.create(f"w{i}", f"a{i}", f"n{i}"),
                       AreaIdentifier(f"w{i}", f"a{i}")) for i in range(6)
    ]
    database = tuple(elevators)

    # Run
    result = elevator_distributor.one_way_elevator_connections(
        rng, database, target_locations, replacement)

    # Assert
    assert result == expected
Beispiel #10
0
def test_replace_node_unknown_node(game_editor):
    # Setup
    world_list = game_editor.game.world_list
    loc = AreaIdentifier("Temple Grounds", "Landing Site")
    loc2 = AreaIdentifier("Temple Grounds", "Service Access")

    landing_site = world_list.area_by_area_location(loc)
    dock = world_list.area_by_area_location(loc2).node_with_name(
        "Door to Landing Site")

    # Run
    with pytest.raises(
            ValueError,
            match=
            "Given Door to Landing Site does does not belong to Landing Site."
    ):
        game_editor.replace_node(landing_site, dock, dock)
Beispiel #11
0
    def static_teleporters(self) -> Dict[NodeIdentifier, AreaIdentifier]:
        static = {}
        if self.skip_final_bosses:
            if self.game == RandovaniaGame.METROID_PRIME:
                crater = NodeIdentifier.create(
                    "Tallon Overworld", "Artifact Temple",
                    "Teleport to Impact Crater - Crater Impact Point")
                static[crater] = AreaIdentifier("End of Game", "Credits")
            elif self.game == RandovaniaGame.METROID_PRIME_ECHOES:
                gateway = NodeIdentifier.create(
                    "Temple Grounds", "Sky Temple Gateway",
                    "Teleport to Great Temple - Sky Temple Energy Controller")
                static[gateway] = AreaIdentifier("Temple Grounds", "Credits")
            else:
                raise ValueError(
                    f"Unsupported skip_final_bosses and {self.game}")

        return static
def _location_with_data(request, mocker, echoes_game_description):
    world_list = echoes_game_description.world_list
    areas = list(itertools.islice(
        (AreaIdentifier(world.name, area.name)
         for world in world_list.worlds
         for area in world.areas
         if area.valid_starting_location), 15))

    mocker.patch("randovania.layout.lib.location_list.LocationList.areas_list",
                 return_value=list(sorted(areas)))
    return request.param["encoded"], LocationList.from_json(request.param["json"], RandovaniaGame.METROID_PRIME_ECHOES)
Beispiel #13
0
def area_locations_with_filter(
        game: RandovaniaGame,
        condition: Callable[[Area], bool]) -> list[AreaIdentifier]:
    world_list = default_database.game_description_for(game).world_list
    identifiers = [
        AreaIdentifier(
            world_name=world.name,
            area_name=area.name,
        ) for world in world_list.worlds for area in world.areas
        if condition(area)
    ]
    return _sorted_area_identifiers(identifiers)
Beispiel #14
0
def test_add_relative_hint(echoes_game_description, echoes_game_patches,
                           precise_distance, location_precision,
                           echoes_item_database):
    # Setup
    rng = Random(5000)
    target_precision = MagicMock(spec=HintItemPrecision)
    precision = MagicMock(spec=HintItemPrecision)
    patches = echoes_game_patches.assign_new_pickups([
        (PickupIndex(8),
         PickupTarget(
             _make_pickup(echoes_item_database.item_categories["movement"]),
             0)),
    ])
    hint_distributor = EchoesHintDistributor()

    if location_precision == HintLocationPrecision.RELATIVE_TO_AREA:
        max_distance = 8
        data = RelativeDataArea(
            None if precise_distance else 3,
            # Was Industrial Site
            AreaIdentifier("Temple Grounds", "Hive Chamber A"),
            precision,
        )
    else:
        max_distance = 20
        data = RelativeDataItem(
            None if precise_distance else 11,
            PickupIndex(8),
            precision,
        )

    # Run
    result = hint_distributor.add_relative_hint(
        echoes_game_description.world_list,
        patches,
        rng,
        PickupIndex(1),
        target_precision,
        location_precision,
        precise_distance,
        precision,
        max_distance=max_distance,
    )

    # Assert
    pair = PrecisionPair(location_precision,
                         target_precision,
                         include_owner=False,
                         relative=data)
    assert result == Hint(HintType.LOCATION, pair, PickupIndex(1))
Beispiel #15
0
def test_edit_connections(game_editor):
    # Setup
    landing_site = game_editor.game.world_list.area_by_area_location(
        AreaIdentifier("Temple Grounds", "Landing Site"))
    source = landing_site.node_with_name("Save Station")
    target = landing_site.node_with_name("Door to Service Access")
    assert landing_site.connections[source][target] != Requirement.trivial()

    # Run
    game_editor.edit_connections(landing_site, source, target,
                                 Requirement.trivial())

    # Assert
    assert landing_site.connections[source][target] == Requirement.trivial()
def test_quick_fill_cs_classic(skip_qtbot, preset_manager):
    # Setup
    base = preset_manager.default_preset_for_game(
        RandovaniaGame.CAVE_STORY).get_preset()
    preset = dataclasses.replace(
        base,
        uuid=uuid.UUID('b41fde84-1f57-4b79-8cd6-3e5a78077fa6'),
        base_preset_uuid=base.uuid)
    editor = PresetEditor(preset)
    window = PresetCSStartingArea(
        editor, default_database.game_description_for(preset.game))
    skip_qtbot.addWidget(window)

    # Run
    skip_qtbot.mouseClick(window.starting_area_quick_fill_classic,
                          QtCore.Qt.LeftButton)

    # Assert
    expected = {
        AreaIdentifier("Mimiga Village", "Start Point"),
        AreaIdentifier("Mimiga Village", "Arthur's House"),
        AreaIdentifier("Labyrinth", "Camp")
    }
    assert set(editor.configuration.starting_location.locations) == expected
Beispiel #17
0
def test_remove_node(game_editor):
    # Setup
    world_list = game_editor.game.world_list
    loc = AreaIdentifier("Temple Grounds", "Landing Site")

    landing_site = world_list.area_by_area_location(loc)
    node = landing_site.node_with_name("Door to Service Access")
    assert node is not None

    # Run
    game_editor.remove_node(landing_site, node)

    # Assert
    assert world_list.area_by_area_location(loc).node_with_name(
        "Door to Service Access") is None
Beispiel #18
0
def test_two_way_elevator_connections_unchecked():
    # Setup
    rng = random.Random(5000)
    elevators = [
        ElevatorHelper(NodeIdentifier.create(f"w{i}", f"a{i}", f"n{i}"),
                       AreaIdentifier(f"w{i}", f"a{i}")) for i in range(6)
    ]
    database = tuple(elevators)

    # Run
    result = elevator_distributor.two_way_elevator_connections(
        rng, database, False)

    # Assert
    assert result == {
        NodeIdentifier.create("w0", "a0", "n0"): AreaIdentifier("w4", "a4"),
        NodeIdentifier.create("w1", "a1", "n1"): AreaIdentifier("w2", "a2"),
        NodeIdentifier.create("w2", "a2", "n2"): AreaIdentifier("w1", "a1"),
        NodeIdentifier.create("w3", "a3", "n3"): AreaIdentifier("w5", "a5"),
        NodeIdentifier.create("w4", "a4", "n4"): AreaIdentifier("w0", "a0"),
        NodeIdentifier.create("w5", "a5", "n5"): AreaIdentifier("w3", "a3"),
    }
Beispiel #19
0
    def create_new_node(self) -> Node:
        node_type = self.node_type_combo.currentData()
        identifier = dataclasses.replace(self.node.identifier, node_name=self.name_edit.text())
        heal = self.heals_check.isChecked()
        location = None
        if self.location_group.isChecked():
            location = NodeLocation(self.location_x_spin.value(),
                                    self.location_y_spin.value(),
                                    self.location_z_spin.value())
        description = self.description_edit.toMarkdown()
        extra = json.loads(self.extra_edit.toPlainText())
        layers = (self.layers_combo.currentText(),)

        if node_type == GenericNode:
            return GenericNode(identifier, heal, location, description, layers, extra)

        elif node_type == DockNode:
            connection_node: Node = self.dock_connection_node_combo.currentData()

            return DockNode(
                identifier, heal, location, description, layers, extra,
                self.dock_type_combo.currentData(),
                self.game.world_list.identifier_for_node(connection_node),
                self.dock_weakness_combo.currentData(),
                None, None,
            )

        elif node_type == PickupNode:
            return PickupNode(
                identifier, heal, location, description, layers, extra,
                PickupIndex(self.pickup_index_spin.value()),
                self.major_location_check.isChecked(),
            )

        elif node_type == TeleporterNode:
            dest_world: World = self.teleporter_destination_world_combo.currentData()
            dest_area: Area = self.teleporter_destination_area_combo.currentData()

            return TeleporterNode(
                identifier, heal, location, description, layers, extra,
                AreaIdentifier(
                    world_name=dest_world.name,
                    area_name=dest_area.name,
                ),
                self.teleporter_vanilla_name_edit.isChecked(),
                self.teleporter_editable_check.isChecked(),
            )

        elif node_type == EventNode:
            event = self.event_resource_combo.currentData()
            if event is None:
                raise ValueError("There are no events in the database, unable to create EventNode.")
            return EventNode(
                identifier, heal, location, description, layers, extra,
                event,
            )

        elif node_type == ConfigurableNode:
            return ConfigurableNode(
                identifier, heal, location, description, layers, extra,
            )

        elif node_type == LogbookNode:
            lore_type: LoreType = self.lore_type_combo.currentData()
            if lore_type == LoreType.REQUIRES_ITEM:
                required_translator = self.logbook_extra_combo.currentData()
                if required_translator is None:
                    raise ValueError("Missing required translator.")
            else:
                required_translator = None

            if lore_type == LoreType.SPECIFIC_PICKUP:
                hint_index = self.logbook_extra_combo.currentData()
            else:
                hint_index = None

            return LogbookNode(
                identifier, heal, location, description, layers, extra,
                int(self.logbook_string_asset_id_edit.text(), 0),
                self._get_scan_visor(),
                lore_type,
                required_translator,
                hint_index
            )

        elif node_type == PlayerShipNode:
            return PlayerShipNode(
                identifier, heal, location, description, layers, extra,
                self._unlocked_by_requirement,
                self._get_command_visor()
            )

        else:
            raise RuntimeError(f"Unknown node type: {node_type}")
Beispiel #20
0
 def create(cls, world_name: str, area_name: str, node_name: str) -> "NodeIdentifier":
     return cls(AreaIdentifier(world_name, area_name), node_name)
Beispiel #21
0
            default_echoes_configuration.major_items_configuration,
            minimum_random_starting_items=2,
        ),
        sky_temple_keys=LayoutSkyTempleKeyMode.ALL_BOSSES,
    )

    # Run
    result = pool_creator.calculate_pool_item_count(layout_configuration)

    # Assert
    assert result == (118, 121)


@pytest.mark.parametrize("puppies", [False, True])
@pytest.mark.parametrize("starting_area", [
    AreaIdentifier("Mimiga Village", "Start Point"),
    AreaIdentifier("Labyrinth", "Camp")
])
def test_cs_item_pool_creator(default_cs_configuration: CSConfiguration,
                              puppies, starting_area):
    game_description = default_database.game_description_for(
        default_cs_configuration.game)
    default_cs_configuration = dataclasses.replace(default_cs_configuration,
                                                   puppies_anywhere=puppies)
    tricks = default_cs_configuration.trick_level.set_level_for_trick(
        game_description.resource_database.get_by_type_and_index(
            ResourceType.TRICK, "SNBubbler"), LayoutTrickLevel.HYPERMODE)
    tricks = tricks.set_level_for_trick(
        game_description.resource_database.get_by_type_and_index(
            ResourceType.TRICK, "SNMissiles"), LayoutTrickLevel.HYPERMODE)
    default_cs_configuration = dataclasses.replace(default_cs_configuration,
 def add(world: str, area: str, node: str, target_world: str,
         target_area: str):
     elevator_connection.append((
         wl.get_teleporter_node(NodeIdentifier.create(world, area, node)),
         AreaIdentifier(target_world, target_area),
     ))
Beispiel #23
0
        rng, database, False)

    # Assert
    assert result == {
        NodeIdentifier.create("w0", "a0", "n0"): AreaIdentifier("w4", "a4"),
        NodeIdentifier.create("w1", "a1", "n1"): AreaIdentifier("w2", "a2"),
        NodeIdentifier.create("w2", "a2", "n2"): AreaIdentifier("w1", "a1"),
        NodeIdentifier.create("w3", "a3", "n3"): AreaIdentifier("w5", "a5"),
        NodeIdentifier.create("w4", "a4", "n4"): AreaIdentifier("w0", "a0"),
        NodeIdentifier.create("w5", "a5", "n5"): AreaIdentifier("w3", "a3"),
    }


@pytest.mark.parametrize(["replacement", "expected"], [
    (False, {
        NodeIdentifier.create("w0", "a0", "n0"): AreaIdentifier("w1", "a1"),
        NodeIdentifier.create("w1", "a1", "n1"): AreaIdentifier("w2", "a2"),
        NodeIdentifier.create("w2", "a2", "n2"): AreaIdentifier("w3", "a3"),
        NodeIdentifier.create("w3", "a3", "n3"): AreaIdentifier("w5", "a5"),
        NodeIdentifier.create("w4", "a4", "n4"): AreaIdentifier("w0", "a0"),
        NodeIdentifier.create("w5", "a5", "n5"): AreaIdentifier("w4", "a4"),
    }),
    (True, {
        NodeIdentifier.create("w0", "a0", "n0"): AreaIdentifier("w2", "a2"),
        NodeIdentifier.create("w1", "a1", "n1"): AreaIdentifier("w3", "a3"),
        NodeIdentifier.create("w2", "a2", "n2"): AreaIdentifier("w4", "a4"),
        NodeIdentifier.create("w3", "a3", "n3"): AreaIdentifier("w2", "a2"),
        NodeIdentifier.create("w4", "a4", "n4"): AreaIdentifier("w5", "a5"),
        NodeIdentifier.create("w5", "a5", "n5"): AreaIdentifier("w3", "a3"),
    }),
])
Beispiel #24
0
 def add(world: str, area: str, node: str, target_world: str, target_area: str):
     elevator_connection[NodeIdentifier.create(world, area, node)] = AreaIdentifier(target_world, target_area)
Beispiel #25
0
def _a(world, area, instance_id=None):
    if instance_id is not None:
        return NodeIdentifier.create(world, area, instance_id).as_json
    return AreaIdentifier(world, area).as_json
Beispiel #26
0
    def setup_elevators(self):
        self._elevator_id_to_combo = {}

        if not hasattr(self.game_configuration, "elevators"):
            return

        elevators_config: TeleporterConfiguration = getattr(
            self.game_configuration, "elevators")

        world_list = self.game_description.world_list
        nodes_by_world: Dict[
            str, List[TeleporterNode]] = collections.defaultdict(list)

        areas_to_not_change = {
            "Sky Temple Gateway",
            "Sky Temple Energy Controller",
            "Aerie Transport Station",
            "Aerie",
        }
        targets = {}
        for world, area, node in world_list.all_worlds_areas_nodes:
            if isinstance(
                    node, TeleporterNode
            ) and node.editable and area.name not in areas_to_not_change:
                name = world.correct_name(area.in_dark_aether)
                nodes_by_world[name].append(node)

                location = AreaIdentifier(world.name, area.name)
                targets[elevators.get_short_elevator_or_area_name(
                    self.game_configuration.game, world_list, location,
                    True)] = location

        if elevators_config.mode == TeleporterShuffleMode.ONE_WAY_ANYTHING:
            targets = {}
            for world in world_list.worlds:
                for area in world.areas:
                    name = world.correct_name(area.in_dark_aether)
                    targets[f"{name} - {area.name}"] = AreaIdentifier(
                        world.name, area.name)

        combo_targets = sorted(targets.items(), key=lambda it: it[0])

        for world_name in sorted(nodes_by_world.keys()):
            nodes = nodes_by_world[world_name]
            nodes_locations = [
                world_list.identifier_for_node(node).area_location
                for node in nodes
            ]
            nodes_names = [
                elevators.get_short_elevator_or_area_name(
                    self.game_configuration.game, world_list, location, False)
                for location in nodes_locations
            ]

            group = QtWidgets.QGroupBox(self.elevators_scroll_contents)
            group.setTitle(world_name)
            self.elevators_scroll_layout.addWidget(group)
            layout = QtWidgets.QGridLayout(group)

            for i, (node, location, name) in enumerate(
                    sorted(zip(nodes, nodes_locations, nodes_names),
                           key=lambda it: it[2])):
                node_name = QtWidgets.QLabel(group)
                node_name.setText(name)
                node_name.setWordWrap(True)
                node_name.setMinimumWidth(75)
                layout.addWidget(node_name, i, 0)

                combo = QtWidgets.QComboBox(group)
                if elevators_config.is_vanilla:
                    combo.addItem("Vanilla", node.default_connection)
                    combo.setEnabled(False)
                else:
                    combo.addItem("Undefined", None)
                    for target_name, connection in combo_targets:
                        combo.addItem(target_name, connection)

                combo.setMinimumContentsLength(11)
                combo.currentIndexChanged.connect(
                    self.update_locations_tree_for_reachable_nodes)
                self._elevator_id_to_combo[world_list.identifier_for_node(
                    node)] = combo
                layout.addWidget(combo, i, 1)
Beispiel #27
0
 def node_to_area_location(self, node: Node) -> AreaIdentifier:
     return AreaIdentifier(
         world_name=self.nodes_to_world(node).name,
         area_name=self.nodes_to_area(node).name,
     )
Beispiel #28
0
 def identifier_for_area(self, area: Area) -> AreaIdentifier:
     world = self.world_with_area(area)
     return AreaIdentifier(world_name=world.name, area_name=area.name)
Beispiel #29
0
 def ni(w: str, a: str, n: str, tw: str, ta: str):
     elevator_connection[NodeIdentifier.create(w, a, n)] = AreaIdentifier(tw, ta)