| 
									
										
										
										
											2023-04-07 18:04:34 -06:00
										 |  |  | from typing import Dict, Set, List, Any | 
					
						
							| 
									
										
										
										
											2023-02-23 23:33:09 -07:00
										 |  |  | from collections import Counter | 
					
						
							|  |  |  | from BaseClasses import Region, Entrance, Location, Item, Tutorial, ItemClassification | 
					
						
							|  |  |  | from ..AutoWorld import World, WebWorld | 
					
						
							|  |  |  | from .Items import base_id, item_table, group_table, tears_set, reliquary_set, skill_set | 
					
						
							|  |  |  | from .Locations import location_table, shop_set | 
					
						
							|  |  |  | from .Exits import region_exit_table, exit_lookup_table | 
					
						
							|  |  |  | from .Rules import rules | 
					
						
							|  |  |  | from worlds.generic.Rules import set_rule | 
					
						
							|  |  |  | from .Options import blasphemous_options | 
					
						
							|  |  |  | from . import Vanilla | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BlasphemousWeb(WebWorld): | 
					
						
							|  |  |  |     theme = "stone" | 
					
						
							|  |  |  |     tutorials = [Tutorial( | 
					
						
							|  |  |  |         "Multiworld Setup Guide", | 
					
						
							|  |  |  |         "A guide to setting up the Blasphemous randomizer connected to an Archipelago Multiworld", | 
					
						
							|  |  |  |         "English", | 
					
						
							|  |  |  |         "setup_en.md", | 
					
						
							|  |  |  |         "setup/en", | 
					
						
							|  |  |  |         ["TRPG"] | 
					
						
							|  |  |  |     )] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BlasphemousWorld(World): | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     Blasphemous is a challenging Metroidvania set in the cursed land of Cvstodia. Play as the Penitent One, trapped | 
					
						
							|  |  |  |     in an endless cycle of death and rebirth, and free the world from it's terrible fate in your quest to break | 
					
						
							|  |  |  |     your eternal damnation! | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     game: str = "Blasphemous" | 
					
						
							|  |  |  |     web = BlasphemousWeb() | 
					
						
							| 
									
										
										
										
											2023-04-06 01:19:58 +02:00
										 |  |  |     data_version = 1 | 
					
						
							| 
									
										
										
										
											2023-02-23 23:33:09 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     item_name_to_id = {item["name"]: (base_id + index) for index, item in enumerate(item_table)} | 
					
						
							|  |  |  |     location_name_to_id = {loc["name"]: (base_id + index) for index, loc in enumerate(location_table)} | 
					
						
							|  |  |  |     location_name_to_game_id = {loc["name"]: loc["game_id"] for loc in location_table} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     item_name_groups = group_table | 
					
						
							|  |  |  |     option_definitions = blasphemous_options | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def set_rules(self): | 
					
						
							|  |  |  |         rules(self) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_item(self, name: str) -> "BlasphemousItem": | 
					
						
							|  |  |  |         item_id: int = self.item_name_to_id[name] | 
					
						
							|  |  |  |         id = item_id - base_id | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return BlasphemousItem(name, item_table[id]["classification"], item_id, player=self.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_event(self, event: str): | 
					
						
							|  |  |  |         return BlasphemousItem(event, ItemClassification.progression_skip_balancing, None, self.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_filler_item_name(self) -> str: | 
					
						
							|  |  |  |         return self.multiworld.random.choice(tears_set) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-07 18:04:34 -06:00
										 |  |  |     def create_items(self): | 
					
						
							| 
									
										
										
										
											2023-02-23 23:33:09 -07:00
										 |  |  |         placed_items = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         placed_items.extend(Vanilla.unrandomized_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.reliquary_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(reliquary_set) | 
					
						
							|  |  |  |         elif self.multiworld.reliquary_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.append("Tears of Atonement (250)") | 
					
						
							|  |  |  |             placed_items.append("Tears of Atonement (300)") | 
					
						
							|  |  |  |             placed_items.append("Tears of Atonement (500)") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.cherub_shuffle[self.player]: | 
					
						
							|  |  |  |             for i in range(38): | 
					
						
							|  |  |  |                 placed_items.append("Child of Moonlight") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.life_shuffle[self.player]: | 
					
						
							|  |  |  |             for i in range(6): | 
					
						
							|  |  |  |                 placed_items.append("Life Upgrade") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.fervour_shuffle[self.player]: | 
					
						
							|  |  |  |             for i in range(6): | 
					
						
							|  |  |  |                 placed_items.append("Fervour Upgrade") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.sword_shuffle[self.player]: | 
					
						
							|  |  |  |             for i in range(7): | 
					
						
							|  |  |  |                 placed_items.append("Mea Culpa Upgrade") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.blessing_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.blessing_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.dungeon_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.dungeon_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.tirso_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.tirso_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.miriam_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.append("Cantina of the Blue Rose") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.redento_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.redento_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.jocinero_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.jocinero_dict.values()) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         if not self.multiworld.altasgracias_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.altasgracias_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.tentudia_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.tentudia_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.gemino_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.gemino_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.guilt_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.append("Weight of True Guilt") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.ossuary_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.ossuary_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.boss_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.boss_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.wound_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.wound_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.mask_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.mask_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.eye_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.eye_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.herb_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.herb_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.church_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.church_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.shop_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.shop_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.multiworld.thorn_shuffle[self.player] == 2: | 
					
						
							|  |  |  |             for i in range(8): | 
					
						
							|  |  |  |                 placed_items.append("Thorn Upgrade") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.candle_shuffle[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.candle_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.multiworld.start_wheel[self.player]: | 
					
						
							|  |  |  |             placed_items.append("The Young Mason's Wheel") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.skill_randomizer[self.player]: | 
					
						
							|  |  |  |             placed_items.extend(Vanilla.skill_dict.values()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         counter = Counter(placed_items) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         pool = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for item in item_table: | 
					
						
							|  |  |  |             count = item["count"] - counter[item["name"]] | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             if count <= 0: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 for i in range(count): | 
					
						
							|  |  |  |                     pool.append(self.create_item(item["name"])) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.multiworld.itempool += pool | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def pre_fill(self): | 
					
						
							|  |  |  |         self.place_items_from_dict(Vanilla.unrandomized_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.cherub_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_set(Vanilla.cherub_set, "Child of Moonlight") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.life_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_set(Vanilla.life_set, "Life Upgrade") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.fervour_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_set(Vanilla.fervour_set, "Fervour Upgrade") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.sword_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_set(Vanilla.sword_set, "Mea Culpa Upgrade") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.blessing_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.blessing_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.dungeon_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.dungeon_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.tirso_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.tirso_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.miriam_shuffle[self.player]: | 
					
						
							|  |  |  |             self.multiworld.get_location("AtTotS: Miriam's gift", self.player)\ | 
					
						
							|  |  |  |                 .place_locked_item(self.create_item("Cantina of the Blue Rose")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.redento_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.redento_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.jocinero_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.jocinero_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.altasgracias_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.altasgracias_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.tentudia_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.tentudia_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.gemino_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.gemino_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.guilt_shuffle[self.player]: | 
					
						
							|  |  |  |             self.multiworld.get_location("GotP: Confessor Dungeon room", self.player)\ | 
					
						
							|  |  |  |                 .place_locked_item(self.create_item("Weight of True Guilt")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.ossuary_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.ossuary_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.boss_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.boss_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.wound_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.wound_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.mask_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.mask_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.eye_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.eye_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.herb_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.herb_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.church_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.church_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.shop_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.shop_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.multiworld.thorn_shuffle[self.player] == 2: | 
					
						
							|  |  |  |             self.place_items_from_set(Vanilla.thorn_set, "Thorn Upgrade") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.candle_shuffle[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.candle_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.multiworld.start_wheel[self.player]: | 
					
						
							|  |  |  |             self.multiworld.get_location("BotSS: Beginning gift", self.player)\ | 
					
						
							|  |  |  |                 .place_locked_item(self.create_item("The Young Mason's Wheel")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if not self.multiworld.skill_randomizer[self.player]: | 
					
						
							|  |  |  |             self.place_items_from_dict(Vanilla.skill_dict) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.multiworld.thorn_shuffle[self.player] == 1: | 
					
						
							|  |  |  |             self.multiworld.local_items[self.player].value.add("Thorn Upgrade") | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def place_items_from_set(self, location_set: Set[str], name: str): | 
					
						
							|  |  |  |         for loc in location_set: | 
					
						
							|  |  |  |             self.multiworld.get_location(loc, self.player)\ | 
					
						
							|  |  |  |                 .place_locked_item(self.create_item(name)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     def place_items_from_dict(self, option_dict: Dict[str, str]): | 
					
						
							|  |  |  |         for loc, item in option_dict.items(): | 
					
						
							|  |  |  |             self.multiworld.get_location(loc, self.player)\ | 
					
						
							|  |  |  |                 .place_locked_item(self.create_item(item)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_regions(self) -> None: | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         player = self.player | 
					
						
							|  |  |  |         world = self.multiworld | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         region_table: Dict[str, Region] = { | 
					
						
							|  |  |  |             "menu"    : Region("Menu", player, world), | 
					
						
							|  |  |  |             "albero"  : Region("Albero", player, world), | 
					
						
							|  |  |  |             "attots"  : Region("All the Tears of the Sea", player, world), | 
					
						
							|  |  |  |             "ar"      : Region("Archcathedral Rooftops", player, world), | 
					
						
							|  |  |  |             "bottc"   : Region("Bridge of the Three Cavalries", player, world), | 
					
						
							|  |  |  |             "botss"   : Region("Brotherhood of the Silent Sorrow", player, world), | 
					
						
							|  |  |  |             "coolotcv": Region("Convent of Our Lady of the Charred Visage", player, world), | 
					
						
							|  |  |  |             "dohh"    : Region("Deambulatory of His Holiness", player, world), | 
					
						
							|  |  |  |             "dc"      : Region("Desecrated Cistern", player, world), | 
					
						
							|  |  |  |             "eos"     : Region("Echoes of Salt", player, world), | 
					
						
							|  |  |  |             "ft"      : Region("Ferrous Tree", player, world), | 
					
						
							|  |  |  |             "gotp"    : Region("Graveyard of the Peaks", player, world), | 
					
						
							|  |  |  |             "ga"      : Region("Grievance Ascends", player, world), | 
					
						
							|  |  |  |             "hotd"    : Region("Hall of the Dawning", player, world), | 
					
						
							|  |  |  |             "jondo"   : Region("Jondo", player, world), | 
					
						
							|  |  |  |             "kottw"   : Region("Knot of the Three Words", player, world), | 
					
						
							|  |  |  |             "lotnw"   : Region("Library of the Negated Words", player, world), | 
					
						
							|  |  |  |             "md"      : Region("Mercy Dreams", player, world), | 
					
						
							|  |  |  |             "mom"     : Region("Mother of Mothers", player, world), | 
					
						
							|  |  |  |             "moted"   : Region("Mountains of the Endless Dusk", player, world), | 
					
						
							|  |  |  |             "mah"     : Region("Mourning and Havoc", player, world), | 
					
						
							|  |  |  |             "potss"   : Region("Patio of the Silent Steps", player, world), | 
					
						
							|  |  |  |             "petrous" : Region("Petrous", player, world), | 
					
						
							|  |  |  |             "thl"     : Region("The Holy Line", player, world), | 
					
						
							|  |  |  |             "trpots"  : Region("The Resting Place of the Sister", player, world), | 
					
						
							|  |  |  |             "tsc"     : Region("The Sleeping Canvases", player, world), | 
					
						
							|  |  |  |             "wothp"   : Region("Wall of the Holy Prohibitions", player, world), | 
					
						
							|  |  |  |             "wotbc"   : Region("Wasteland of the Buried Churches", player, world), | 
					
						
							|  |  |  |             "wotw"    : Region("Where Olive Trees Wither", player, world), | 
					
						
							|  |  |  |             "dungeon" : Region("Dungeons", player, world) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for rname, reg in region_table.items(): | 
					
						
							|  |  |  |             world.regions.append(reg) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for ename, exits in region_exit_table.items(): | 
					
						
							|  |  |  |                 if ename == rname: | 
					
						
							|  |  |  |                     for i in exits: | 
					
						
							|  |  |  |                         ent = Entrance(player, i, reg) | 
					
						
							|  |  |  |                         reg.exits.append(ent) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         for e, r in exit_lookup_table.items(): | 
					
						
							|  |  |  |                             if i == e: | 
					
						
							|  |  |  |                                 ent.connect(region_table[r]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for loc in location_table: | 
					
						
							|  |  |  |             id = base_id + location_table.index(loc) | 
					
						
							|  |  |  |             region_table[loc["region"]].locations\ | 
					
						
							|  |  |  |                 .append(BlasphemousLocation(self.player, loc["name"], id, region_table[loc["region"]])) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         victory = Location(self.player, "His Holiness Escribar", None, self.multiworld.get_region("Deambulatory of His Holiness", self.player)) | 
					
						
							|  |  |  |         victory.place_locked_item(self.create_event("Victory")) | 
					
						
							|  |  |  |         self.multiworld.get_region("Deambulatory of His Holiness", self.player).locations.append(victory) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if self.multiworld.ending[self.player].value == 1: | 
					
						
							|  |  |  |             set_rule(victory, lambda state: state.has("Thorn Upgrade", player, 8)) | 
					
						
							|  |  |  |         elif self.multiworld.ending[self.player].value == 2: | 
					
						
							|  |  |  |             set_rule(victory, lambda state: state.has("Thorn Upgrade", player, 8) and \ | 
					
						
							|  |  |  |                 state.has("Holy Wound of Abnegation", player)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.multiworld.completion_condition[self.player] = lambda state: state.has("Victory", self.player) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     def fill_slot_data(self) -> Dict[str, Any]: | 
					
						
							|  |  |  |         slot_data: Dict[str, Any] = {} | 
					
						
							|  |  |  |         locations = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for loc in self.multiworld.get_filled_locations(self.player): | 
					
						
							|  |  |  |             if loc.name == "His Holiness Escribar": | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 data = { | 
					
						
							|  |  |  |                     "id": self.location_name_to_game_id[loc.name], | 
					
						
							|  |  |  |                     "ap_id": loc.address, | 
					
						
							|  |  |  |                     "name": loc.item.name, | 
					
						
							|  |  |  |                     "player_name": self.multiworld.player_name[loc.item.player] | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if loc.name in shop_set: | 
					
						
							|  |  |  |                     data["type"] = loc.item.classification.name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 locations.append(data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         config = { | 
					
						
							|  |  |  |             "versionCreated": "AP", | 
					
						
							|  |  |  |             "general": { | 
					
						
							|  |  |  |                 "teleportationAlwaysUnlocked": bool(self.multiworld.prie_dieu_warp[self.player].value), | 
					
						
							|  |  |  |                 "skipCutscenes": bool(self.multiworld.skip_cutscenes[self.player].value), | 
					
						
							|  |  |  |                 "enablePenitence": bool(self.multiworld.penitence[self.player].value), | 
					
						
							|  |  |  |                 "hardMode": False, | 
					
						
							|  |  |  |                 "customSeed": 0, | 
					
						
							|  |  |  |                 "allowHints": bool(self.multiworld.corpse_hints[self.player].value) | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "items": { | 
					
						
							|  |  |  |                 "type": 1, | 
					
						
							|  |  |  |                 "lungDamage": False, | 
					
						
							|  |  |  |                 "disableNPCDeath": True, | 
					
						
							|  |  |  |                 "startWithWheel": bool(self.multiworld.start_wheel[self.player].value), | 
					
						
							|  |  |  |                 "shuffleReliquaries": bool(self.multiworld.reliquary_shuffle[self.player].value) | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "enemies": { | 
					
						
							|  |  |  |                 "type": self.multiworld.enemy_randomizer[self.player].value, | 
					
						
							|  |  |  |                 "maintainClass": bool(self.multiworld.enemy_groups[self.player].value), | 
					
						
							|  |  |  |                 "areaScaling": bool(self.multiworld.enemy_scaling[self.player].value) | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "prayers": { | 
					
						
							|  |  |  |                 "type": 0, | 
					
						
							|  |  |  |                 "removeMirabis": False | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "doors": { | 
					
						
							|  |  |  |                 "type": 0 | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             "debug": { | 
					
						
							|  |  |  |                 "type": 0 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |         slot_data = { | 
					
						
							|  |  |  |             "locations": locations, | 
					
						
							|  |  |  |             "cfg": config, | 
					
						
							|  |  |  |             "ending": self.multiworld.ending[self.player].value, | 
					
						
							|  |  |  |             "death_link": bool(self.multiworld.death_link[self.player].value) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |         return slot_data | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BlasphemousItem(Item): | 
					
						
							|  |  |  |     game: str = "Blasphemous" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class BlasphemousLocation(Location): | 
					
						
							|  |  |  |     game: str = "Blasphemous" |