forked from mirror/Archipelago
206 lines
7.6 KiB
Python
206 lines
7.6 KiB
Python
from typing import Any, Dict, List, Tuple
|
|
|
|
from BaseClasses import Item, ItemClassification, Location, Region, Tutorial
|
|
|
|
from worlds.AutoWorld import WebWorld, World
|
|
|
|
from .data.item_data import item_data, ZorkGrandInquisitorItemData
|
|
from .data.location_data import location_data, ZorkGrandInquisitorLocationData
|
|
from .data.region_data import region_data
|
|
|
|
from .data_funcs import (
|
|
item_names_to_id,
|
|
item_names_to_item,
|
|
location_names_to_id,
|
|
item_groups,
|
|
items_with_tag,
|
|
location_groups,
|
|
locations_by_region,
|
|
location_access_rule_for,
|
|
entrance_access_rule_for,
|
|
)
|
|
|
|
from .enums import (
|
|
ZorkGrandInquisitorEvents,
|
|
ZorkGrandInquisitorItems,
|
|
ZorkGrandInquisitorLocations,
|
|
ZorkGrandInquisitorRegions,
|
|
ZorkGrandInquisitorTags,
|
|
)
|
|
|
|
from .options import ZorkGrandInquisitorOptions
|
|
|
|
|
|
class ZorkGrandInquisitorItem(Item):
|
|
game = "Zork Grand Inquisitor"
|
|
|
|
|
|
class ZorkGrandInquisitorLocation(Location):
|
|
game = "Zork Grand Inquisitor"
|
|
|
|
|
|
class ZorkGrandInquisitorWebWorld(WebWorld):
|
|
theme: str = "stone"
|
|
|
|
tutorials: List[Tutorial] = [
|
|
Tutorial(
|
|
"Multiworld Setup Guide",
|
|
"A guide to setting up the Zork Grand Inquisitor randomizer connected to an Archipelago Multiworld",
|
|
"English",
|
|
"setup_en.md",
|
|
"setup/en",
|
|
["Serpent.AI"],
|
|
)
|
|
]
|
|
|
|
|
|
class ZorkGrandInquisitorWorld(World):
|
|
"""
|
|
Zork: Grand Inquisitor is a 1997 point-and-click adventure game for PC.
|
|
Magic has been banned from the great Underground Empire of Zork. By edict of the Grand Inquisitor Mir Yannick, the
|
|
Empire has been sealed off and the practice of mystic arts declared punishable by "Totemization" (a very bad thing).
|
|
The only way to restore magic to the kingdom is to find three hidden artifacts: The Coconut of Quendor, The Cube of
|
|
Foundation, and The Skull of Yoruk.
|
|
"""
|
|
|
|
options_dataclass = ZorkGrandInquisitorOptions
|
|
options: ZorkGrandInquisitorOptions
|
|
|
|
game = "Zork Grand Inquisitor"
|
|
|
|
item_name_to_id = item_names_to_id()
|
|
location_name_to_id = location_names_to_id()
|
|
|
|
item_name_groups = item_groups()
|
|
location_name_groups = location_groups()
|
|
|
|
required_client_version: Tuple[int, int, int] = (0, 4, 4)
|
|
|
|
web = ZorkGrandInquisitorWebWorld()
|
|
|
|
filler_item_names: List[str] = item_groups()["Filler"]
|
|
item_name_to_item: Dict[str, ZorkGrandInquisitorItems] = item_names_to_item()
|
|
|
|
def create_regions(self) -> None:
|
|
deathsanity: bool = bool(self.options.deathsanity)
|
|
|
|
region_mapping: Dict[ZorkGrandInquisitorRegions, Region] = dict()
|
|
|
|
region_enum_item: ZorkGrandInquisitorRegions
|
|
for region_enum_item in region_data.keys():
|
|
region_mapping[region_enum_item] = Region(region_enum_item.value, self.player, self.multiworld)
|
|
|
|
region_locations_mapping: Dict[ZorkGrandInquisitorRegions, List[ZorkGrandInquisitorLocations]]
|
|
region_locations_mapping = locations_by_region(include_deathsanity=deathsanity)
|
|
|
|
region_enum_item: ZorkGrandInquisitorRegions
|
|
region: Region
|
|
for region_enum_item, region in region_mapping.items():
|
|
regions_locations: List[ZorkGrandInquisitorLocations] = region_locations_mapping[region_enum_item]
|
|
|
|
# Locations
|
|
location_enum_item: ZorkGrandInquisitorLocations
|
|
for location_enum_item in regions_locations:
|
|
data: ZorkGrandInquisitorLocationData = location_data[location_enum_item]
|
|
|
|
location: ZorkGrandInquisitorLocation = ZorkGrandInquisitorLocation(
|
|
self.player,
|
|
location_enum_item.value,
|
|
data.archipelago_id,
|
|
region_mapping[data.region],
|
|
)
|
|
|
|
if isinstance(location_enum_item, ZorkGrandInquisitorEvents):
|
|
location.place_locked_item(
|
|
ZorkGrandInquisitorItem(
|
|
data.event_item_name,
|
|
ItemClassification.progression,
|
|
None,
|
|
self.player,
|
|
)
|
|
)
|
|
|
|
location_access_rule: str = location_access_rule_for(location_enum_item, self.player)
|
|
|
|
if location_access_rule != "lambda state: True":
|
|
location.access_rule = eval(location_access_rule)
|
|
|
|
region.locations.append(location)
|
|
|
|
# Connections
|
|
region_exit: ZorkGrandInquisitorRegions
|
|
for region_exit in region_data[region_enum_item].exits or tuple():
|
|
entrance_access_rule: str = entrance_access_rule_for(region_enum_item, region_exit, self.player)
|
|
|
|
if entrance_access_rule == "lambda state: True":
|
|
region.connect(region_mapping[region_exit])
|
|
else:
|
|
region.connect(region_mapping[region_exit], rule=eval(entrance_access_rule))
|
|
|
|
self.multiworld.regions.append(region)
|
|
|
|
def create_items(self) -> None:
|
|
quick_port_foozle: bool = bool(self.options.quick_port_foozle)
|
|
start_with_hotspot_items: bool = bool(self.options.start_with_hotspot_items)
|
|
|
|
item_pool: List[ZorkGrandInquisitorItem] = list()
|
|
|
|
item: ZorkGrandInquisitorItems
|
|
data: ZorkGrandInquisitorItemData
|
|
for item, data in item_data.items():
|
|
tags: Tuple[ZorkGrandInquisitorTags, ...] = data.tags or tuple()
|
|
|
|
if ZorkGrandInquisitorTags.FILLER in tags:
|
|
continue
|
|
elif ZorkGrandInquisitorTags.HOTSPOT in tags and start_with_hotspot_items:
|
|
continue
|
|
|
|
item_pool.append(self.create_item(item.value))
|
|
|
|
total_locations: int = len(self.multiworld.get_unfilled_locations(self.player))
|
|
item_pool += [self.create_filler() for _ in range(total_locations - len(item_pool))]
|
|
|
|
self.multiworld.itempool += item_pool
|
|
|
|
if quick_port_foozle:
|
|
self.multiworld.early_items[self.player][ZorkGrandInquisitorItems.ROPE.value] = 1
|
|
self.multiworld.early_items[self.player][ZorkGrandInquisitorItems.LANTERN.value] = 1
|
|
|
|
if not start_with_hotspot_items:
|
|
self.multiworld.early_items[self.player][ZorkGrandInquisitorItems.HOTSPOT_WELL.value] = 1
|
|
self.multiworld.early_items[self.player][ZorkGrandInquisitorItems.HOTSPOT_JACKS_DOOR.value] = 1
|
|
|
|
self.multiworld.early_items[self.player][
|
|
ZorkGrandInquisitorItems.HOTSPOT_GRAND_INQUISITOR_DOLL.value
|
|
] = 1
|
|
|
|
if start_with_hotspot_items:
|
|
item: ZorkGrandInquisitorItems
|
|
for item in sorted(items_with_tag(ZorkGrandInquisitorTags.HOTSPOT), key=lambda item: item.name):
|
|
self.multiworld.push_precollected(self.create_item(item.value))
|
|
|
|
def create_item(self, name: str) -> ZorkGrandInquisitorItem:
|
|
data: ZorkGrandInquisitorItemData = item_data[self.item_name_to_item[name]]
|
|
|
|
return ZorkGrandInquisitorItem(
|
|
name,
|
|
data.classification,
|
|
data.archipelago_id,
|
|
self.player,
|
|
)
|
|
|
|
def generate_basic(self) -> None:
|
|
self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player)
|
|
|
|
def fill_slot_data(self) -> Dict[str, Any]:
|
|
return self.options.as_dict(
|
|
"goal",
|
|
"quick_port_foozle",
|
|
"start_with_hotspot_items",
|
|
"deathsanity",
|
|
"grant_missable_location_checks",
|
|
)
|
|
|
|
def get_filler_item_name(self) -> str:
|
|
return self.random.choice(self.filler_item_names)
|