syntax = "proto2"; package com.fourisland.lingo2_archipelago; message Proxy { optional string answer = 1; optional string path = 2; } enum DoorType { DOOR_TYPE_UNKNOWN = 0; // This door is a location unless panelsanity is on, and it is an item as long as door shuffle is on. STANDARD = 1; // This door is never an item or a location. EVENT = 2; // This door is never a location, and is an item as long as door shuffle is on. ITEM_ONLY = 3; // This door is never a location, and is an item as long as control center color shuffle is on. CONTROL_CENTER_COLOR = 4; // This door is never an item, and is a location as long as panelsanity is not on. LOCATION_ONLY = 5; // This door is an item if gravestone shuffle is enabled, and is a location as long as panelsanity is not on. GRAVESTONE = 6; // This door is never a location, and is an item as long as gallery painting shuffle is on. GALLERY_PAINTING = 7; } enum DoorGroupType { DOOR_GROUP_TYPE_UNKNOWN = 0; // These doors border a worldport. They should be grouped when connections are // not shuffled. CONNECTOR = 1; // Similar to CONNECTOR, but these doors are also ordinarily opened by solving // the COLOR panel in the Control Center. These should be grouped when // connections are not shuffled, but are not items at all when control center // colors are not shuffled. COLOR_CONNECTOR = 2; // Groups with this type become an item if cyan door behavior is set to item. CYAN_DOORS = 3; // Groups with this type always become an item if door shuffle is on. SHUFFLE_GROUP = 4; } enum AxisDirection { AXIS_DIRECTION_UNKNOWN = 0; X_PLUS = 1; X_MINUS = 2; Y_PLUS = 3; Y_MINUS = 4; Z_PLUS = 5; Z_MINUS = 6; } enum PuzzleSymbol { PUZZLE_SYMBOL_UNKNOWN = 0; SUN = 1; SPARKLES = 2; ZERO = 3; EXAMPLE = 4; BOXES = 5; PLANET = 6; PYRAMID = 7; CROSS = 8; SWEET = 9; GENDER = 10; AGE = 11; SOUND = 12; ANAGRAM = 13; JOB = 14; STARS = 15; NULL = 16; EVAL = 17; LINGO = 18; QUESTION = 19; } message Vec3d { optional double x = 1; optional double y = 2; optional double z = 3; } message VersionNumber { optional uint64 major = 1; optional uint64 minor = 2; optional uint64 patch = 3; } message ProxyIdentifier { optional uint64 panel = 1; optional string answer = 2; } message KeyholderAnswer { optional uint64 keyholder = 1; optional string key = 2; } message Connection { optional uint64 from_room = 1; optional uint64 to_room = 2; optional uint64 required_door = 3; oneof trigger { uint64 port = 4; uint64 painting = 5; ProxyIdentifier panel = 6; } optional bool roof_access = 7; optional bool purple_ending = 8; optional bool cyan_ending = 9; optional bool vanilla_only = 10; } message Door { optional uint64 id = 1; optional uint64 ap_id = 11; optional uint64 map_id = 9; optional uint64 room_id = 10; optional string name = 2; repeated string receivers = 3; repeated uint64 move_paintings = 4; repeated ProxyIdentifier panels = 5; optional uint64 complete_at = 12; optional string control_center_color = 6; repeated KeyholderAnswer keyholders = 13; repeated uint64 rooms = 14; repeated uint64 doors = 15; repeated uint64 endings = 16; optional bool double_letters = 18; repeated string senders = 19; optional DoorType type = 8; optional string location_name = 17; } message PanelData { optional uint64 id = 1; optional uint64 ap_id = 10; optional uint64 room_id = 2; optional string name = 3; optional string path = 4; optional string clue = 5; optional string answer = 6; repeated PuzzleSymbol symbols = 7; repeated Proxy proxies = 8; optional uint64 required_door = 9; optional uint64 required_room = 11; optional string display_name = 12; } message PaintingData { optional uint64 id = 1; optional uint64 room_id = 2; optional string name = 9; optional string path = 10; optional string display_name = 4; optional string orientation = 3; optional bool move = 6; optional bool enter_only = 7; optional AxisDirection gravity = 8; optional bool exit_only = 11; optional uint64 required_door = 5; } message Port { optional uint64 id = 1; optional uint64 room_id = 2; optional string name = 3; optional string display_name = 10; optional string path = 4; optional Vec3d destination = 5; optional double rotation = 8; optional AxisDirection gravity = 7; optional bool no_shuffle = 9; optional uint64 required_door = 6; } message KeyholderData { optional uint64 id = 1; optional uint64 ap_id = 6; optional uint64 room_id = 2; optional string name = 3; optional string path = 4; optional string key = 5; } message Letter { optional uint64 id = 3; optional uint64 ap_id = 5; optional uint64 room_id = 4; optional string key = 1; optional bool level2 = 2; optional string path = 6; } message Mastery { optional uint64 id = 1; optional uint64 ap_id = 2; optional uint64 room_id = 3; optional string name = 4; optional string path = 5; } message Ending { optional uint64 id = 1; optional uint64 ap_id = 2; optional uint64 room_id = 3; optional string name = 4; optional string path = 5; } message Room { opt
"""
Archipelago init file for Lingo 2
"""
from BaseClasses import ItemClassification, Item
from worlds.AutoWorld import WebWorld, World
from .items import Lingo2Item
from .options import Lingo2Options
from .player_logic import Lingo2PlayerLogic
from .regions import create_regions
from .static_logic import Lingo2StaticLogic


class Lingo2WebWorld(WebWorld):
    rich_text_options_doc = True
    theme = "grass"


class Lingo2World(World):
    """
    Lingo 2 is a first person indie puzzle game where you solve word puzzles in a labyrinthe world. Compared to its
    predecessor, Lingo 2 has new mechanics, more areas, and a unique progression system where you have to unlock letters
    before using them in puzzle solutions.
    """
    game = "Lingo 2"
    web = Lingo2WebWorld()

    options_dataclass = Lingo2Options
    options: Lingo2Options

    static_logic = Lingo2StaticLogic()
    item_name_to_id = static_logic.item_name_to_id
    location_name_to_id = static_logic.location_name_to_id

    player_logic: Lingo2PlayerLogic

    def generate_early(self):
        self.player_logic = Lingo2PlayerLogic(self)

    def create_regions(self):
        create_regions(self)

        from Utils import visualize_regions

        visualize_regions(self.multiworld.get_region("Menu", self.player), "my_world.puml")

    def create_items(self):
        pool = [self.create_item(name) for name in self.player_logic.real_items]

        total_locations = sum(len(locs) for locs in self.player_logic.locations_by_room.values())

        item_difference = total_locations - len(pool)
        for i in range(0, item_difference):
            pool.append(self.create_item("Nothing"))

        self.multiworld.itempool += pool

    def create_item(self, name: str) -> Item:
        return Lingo2Item(name, ItemClassification.filler if name == "Nothing" else ItemClassification.progression,
                          self.item_name_to_id.get(name), self.player)