diff --git a/worlds/blasphemous/Exits.py b/worlds/blasphemous/Exits.py new file mode 100644 index 00000000..a4460e2a --- /dev/null +++ b/worlds/blasphemous/Exits.py @@ -0,0 +1,135 @@ +from typing import List, Dict + + +region_exit_table: Dict[str, List[str]] = { + "menu" : ["New Game"], + + "albero" : ["To The Holy Line", + "To Desecrated Cistern", + "To Wasteland of the Buried Churches", + "To Dungeons"], + + "attots" : ["To Mother of Mothers"], + + "ar" : ["To Mother of Mothers", + "To Wall of the Holy Prohibitions", + "To Deambulatory of His Holiness"], + + "bottc" : ["To Wasteland of the Buried Churches", + "To Ferrous Tree"], + + "botss" : ["To The Holy Line", + "To Mountains of the Endless Dusk"], + + "coolotcv" : ["To Graveyard of the Peaks", + "To Wall of the Holy Prohibitions"], + + "dohh" : ["To Archcathedral Rooftops"], + + "dc" : ["To Albero", + "To Mercy Dreams", + "To Mountains of the Endless Dusk", + "To Echoes of Salt", + "To Grievance Ascends"], + + "eos" : ["To Jondo", + "To Mountains of the Endless Dusk", + "To Desecrated Cistern", + "To The Resting Place of the Sister", + "To Mourning and Havoc"], + + "ft" : ["To Bridge of the Three Cavalries", + "To Hall of the Dawning", + "To Patio of the Silent Steps"], + + "gotp" : ["To Where Olive Trees Wither", + "To Convent of Our Lady of the Charred Visage"], + + "ga" : ["To Jondo", + "To Desecrated Cistern"], + + "hotd" : ["To Ferrous Tree"], + + "jondo" : ["To Mountains of the Endless Dusk", + "To Grievance Ascends"], + + "kottw" : ["To Mother of Mothers"], + + "lotnw" : ["To Mother of Mothers", + "To The Sleeping Canvases"], + + "md" : ["To Wasteland of the Buried Churches", + "To Desecrated Cistern", + "To The Sleeping Canvases"], + + "mom" : ["To Patio of the Silent Steps", + "To Archcathedral Rooftops", + "To Knot of the Three Words", + "To Library of the Negated Words", + "To All the Tears of the Sea"], + + "moted" : ["To Brotherhood of the Silent Sorrow", + "To Jondo", + "To Desecrated Cistern"], + + "mah" : ["To Echoes of Salt", + "To Mother of Mothers"], + + "potss" : ["To Ferrous Tree", + "To Mother of Mothers", + "To Wall of the Holy Prohibitions"], + + "petrous" : ["To The Holy Line"], + + "thl" : ["To Brotherhood of the Silent Sorrow", + "To Petrous", + "To Albero"], + + "trpots" : ["To Echoes of Salt"], + + "tsc" : ["To Library of the Negated Words", + "To Mercy Dreams"], + + "wothp" : ["To Archcathedral Rooftops", + "To Convent of Our Lady of the Charred Visage"], + + "wotbc" : ["To Albero", + "To Where Olive Trees Wither", + "To Mercy Dreams"], + + "wotw" : ["To Wasteland of the Buried Churches", + "To Graveyard of the Peaks"] +} + +exit_lookup_table: Dict[str, str] = { + "New Game": "botss", + "To Albero": "albero", + "To All the Tears of the Sea": "attots", + "To Archcathedral Rooftops": "ar", + "To Bridge of the Three Cavalries": "bottc", + "To Brotherhood of the Silent Sorrow": "botss", + "To Convent of Our Lady of the Charred Visage": "coolotcv", + "To Deambulatory of His Holiness": "dohh", + "To Desecrated Cistern": "dc", + "To Echoes of Salt": "eos", + "To Ferrous Tree": "ft", + "To Graveyard of the Peaks": "gotp", + "To Grievance Ascends": "ga", + "To Hall of the Dawning": "hotd", + "To Jondo": "jondo", + "To Knot of the Three Words": "kottw", + "To Library of the Negated Words": "lotnw", + "To Mercy Dreams": "md", + "To Mother of Mothers": "mom", + "To Mountains of the Endless Dusk": "moted", + "To Mourning and Havoc": "mah", + "To Patio of the Silent Steps": "potss", + "To Petrous": "petrous", + "To The Holy Line": "thl", + "To The Resting Place of the Sister": "trpots", + "To The Sleeping Canvases": "tsc", + "To Wall of the Holy Prohibitions": "wothp", + "To Wasteland of the Buried Churches": "wotbc", + "To Where Olive Trees Wither": "wotw", + "To Dungeons": "dungeon" +} \ No newline at end of file diff --git a/worlds/blasphemous/Items.py b/worlds/blasphemous/Items.py new file mode 100644 index 00000000..97dcefde --- /dev/null +++ b/worlds/blasphemous/Items.py @@ -0,0 +1,754 @@ +from BaseClasses import ItemClassification +from typing import TypedDict, Dict, List, Set + + +class ItemDict(TypedDict): + name: str + count: int + classification: ItemClassification + +base_id = 1909000 + +item_table: List[ItemDict] = [ + # Rosary Beads + {'name': "Dove Skull", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Ember of the Holy Cremation", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Silver Grape", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Uvula of Proclamation", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Hollow Pearl", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Knot of Hair", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Painted Wood Bead", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Piece of a Golden Mask", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Moss Preserved in Glass", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Frozen Olive", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Quirce's Scorched Bead", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Wicker Knot", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Perpetva's Protection", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Thorned Symbol", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Piece of a Tombstone", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Sphere of the Sacred Smoke", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Bead of Red Wax", + 'count': 3, + 'classification': ItemClassification.progression}, + {'name': "Little Toe made of Limestone", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Big Toe made of Limestone", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Fourth Toe made of Limestone", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Bead of Blue Wax", + 'count': 3, + 'classification': ItemClassification.progression}, + {'name': "Pelican Effigy", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Drop of Coagulated Ink", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Amber Eye", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Muted Bell", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Consecrated Amethyst", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Embers of a Broken Star", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Scaly Coin", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Seashell of the Inverted Spiral", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Calcified Eye of Erudition", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Weight of True Guilt", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Reliquary of the Fervent Heart", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Reliquary of the Suffering Heart", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Reliquary of the Sorrowful Heart", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Token of Appreciation", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Cloistered Ruby", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Bead of Gold Thread", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Cloistered Sapphire", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Fire Enclosed in Enamel", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Light of the Lady of the Lamp", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Scale of Burnished Alabaster", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "The Young Mason's Wheel", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Crown of Gnawed Iron", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Crimson Heart of a Miura", + 'count': 1, + 'classification': ItemClassification.useful}, + + # Prayers + {'name': "Seguiriya to your Eyes like Stars", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Debla of the Lights", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Saeta Dolorosa", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Campanillero to the Sons of the Aurora", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Lorquiana", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Zarabanda of the Safe Haven", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Taranto to my Sister", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Solea of Excommunication", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Tiento to your Thorned Hairs", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Cante Jondo of the Three Sisters", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Verdiales of the Forsaken Hamlet", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Romance to the Crimson Mist", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Zambra to the Resplendent Crown", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Aubade of the Nameless Guardian", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Cantina of the Blue Rose", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Mirabras of the Return to Port", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Tirana of the Celestial Bastion", + 'count': 1, + 'classification': ItemClassification.progression}, + + # Relics + {'name': "Blood Perpetuated in Sand", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Incorrupt Hand of the Fraternal Master", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Nail Uprooted from Dirt", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Shroud of Dreamt Sins", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Linen of Golden Thread", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Silvered Lung of Dolphos", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Three Gnarled Tongues", + 'count': 1, + 'classification': ItemClassification.progression}, + + # Mea Culpa Hearts + {'name': "Smoking Heart of Incense", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Heart of the Virtuous Pain", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Heart of Saltpeter Blood", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Heart of Oils", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Heart of Cerulean Incense", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Heart of the Holy Purge", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Molten Heart of Boiling Blood", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Heart of the Single Tone", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Heart of the Unnamed Minstrel", + 'count': 1, + 'classification': ItemClassification.useful}, + {'name': "Brilliant Heart of Dawn", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Apodictic Heart of Mea Culpa", + 'count': 1, + 'classification': ItemClassification.progression}, + + # Quest Items + {'name': "Cord of the True Burying", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Mark of the First Refuge", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Mark of the Second Refuge", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Mark of the Third Refuge", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Tentudia's Carnal Remains", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Remains of Tentudia's Hair", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Tentudia's Skeletal Remains", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Melted Golden Coins", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Torn Bridal Ribbon", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Black Grieving Veil", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Egg of Deformity", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Hatched Egg of Deformity", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Bouquet of Rosemary", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Incense Garlic", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Thorn Upgrade", + 'count': 8, + 'classification': ItemClassification.progression}, + {'name': "Olive Seeds", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Holy Wound of Attrition", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Holy Wound of Contrition", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Holy Wound of Compunction", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Empty Bile Vessel", + 'count': 8, + 'classification': ItemClassification.progression}, + {'name': "Knot of Rosary Rope", + 'count': 6, + 'classification': ItemClassification.progression}, + {'name': "Golden Thimble Filled with Burning Oil", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Key to the Chamber of the Eldest Brother", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Empty Golden Thimble", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Deformed Mask of Orestes", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Mirrored Mask of Dolphos", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Embossed Mask of Crescente", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Dried Clove", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Sooty Garlic", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Bouquet of Thyme", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Linen Cloth", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Severed Hand", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Dried Flowers bathed in Tears", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Key of the Secular", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Key of the Scribe", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Key of the Inquisitor", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Key of the High Peaks", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Chalice of Inverted Verses", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Quicksilver", + 'count': 5, + 'classification': ItemClassification.useful}, + {'name': "Petrified Bell", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Verses Spun from Gold", + 'count': 4, + 'classification': ItemClassification.progression}, + {'name': "Severed Right Eye of the Traitor", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Broken Left Eye of the Traitor", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Incomplete Scapular", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Key Grown from Twisted Wood", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Holy Wound of Abnegation", + 'count': 1, + 'classification': ItemClassification.progression}, + + # Skills + {'name': "Combo Skill", + 'count': 3, + 'classification': ItemClassification.useful}, + {'name': "Charged Skill", + 'count': 3, + 'classification': ItemClassification.progression}, + {'name': "Ranged Skill", + 'count': 3, + 'classification': ItemClassification.progression}, + {'name': "Dive Skill", + 'count': 3, + 'classification': ItemClassification.progression}, + {'name': "Lunge Skill", + 'count': 3, + 'classification': ItemClassification.useful}, + + # Other + {'name': "Parietal bone of Lasser, the Inquisitor", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Jaw of Ashgan, the Inquisitor", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Cervical vertebra of Zicher, the Brewmaster", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Clavicle of Dalhuisen, the Schoolchild", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Sternum of Vitas, the Performer", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Ribs of Sabnock, the Guardian", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Vertebra of John, the Gambler", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Scapula of Carlos, the Executioner", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Humerus of McMittens, the Nurse", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Ulna of Koke, the Troubadour", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Radius of Helzer, the Poet", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Frontal of Martinus, the Ropemaker", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Metacarpus of Hodges, the Blacksmith", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Phalanx of Arthur, the Sailor", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Phalanx of Miriam, the Counsellor", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Phalanx of Brannon, the Gravedigger", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Coxal of June, the Prostitute", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Sacrum of the Dark Warlock", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Coccyx of Daniel, the Possessed", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Femur of Karpow, the Bounty Hunter", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Kneecap of Sebastien, the Puppeteer", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Tibia of Alsahli, the Mystic", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Fibula of Rysp, the Ranger", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Temporal of Joel, the Thief", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Metatarsus of Rikusyo, the Traveller", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Phalanx of Zeth, the Prisoner", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Phalanx of William, the Sceptic", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Phalanx of Aralcarim, the Archivist", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Occipital of Tequila, the Metalsmith", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Maxilla of Tarradax, the Cleric", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Nasal bone of Charles, the Artist", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Hyoid bone of Senex, the Beggar", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Vertebra of Lindquist, the Forger", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Trapezium of Jeremiah, the Hangman", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Trapezoid of Yeager, the Jeweller", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Capitate of Barock, the Herald", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Hamate of Vukelich, the Copyist", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Pisiform of Hernandez, the Explorer", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Triquetral of Luca, the Tailor", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Lunate of Keiya, the Butcher", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Scaphoid of Fierce, the Leper", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Anklebone of Weston, the Pilgrim", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Calcaneum of Persian, the Bandit", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Navicular of Kahnnyhoo, the Murderer", + 'count': 1, + 'classification': ItemClassification.progression}, + {'name': "Child of Moonlight", + 'count': 38, + 'classification': ItemClassification.progression}, + {'name': "Life Upgrade", + 'count': 6, + 'classification': ItemClassification.progression}, + {'name': "Fervour Upgrade", + 'count': 6, + 'classification': ItemClassification.progression}, + {'name': "Mea Culpa Upgrade", + 'count': 7, + 'classification': ItemClassification.progression}, + {'name': "Tears of Atonement (250)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (300)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (500)", + 'count': 3, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (625)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (750)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (1000)", + 'count': 4, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (1250)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (1500)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (1750)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (2000)", + 'count': 2, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (2100)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (2500)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (2600)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (3000)", + 'count': 2, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (4300)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (5000)", + 'count': 4, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (5500)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (9000)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (10000)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (11250)", + 'count': 1, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (18000)", + 'count': 5, + 'classification': ItemClassification.filler}, + {'name': "Tears of Atonement (30000)", + 'count': 1, + 'classification': ItemClassification.filler} +] + +group_table: Dict[str, Set[str]] = { + "wounds" : ["Holy Wound of Attrition", + "Holy Wound of Contrition", + "Holy Wound of Compunction"], + + "masks" : ["Deformed Mask of Orestes", + "Mirrored Mask of Dolphos", + "Embossed Mask of Crescente"], + + "tirso" : ["Bouquet of Rosemary", + "Incense Garlic", + "Olive Seeds", + "Dried Clove", + "Sooty Garlic", + "Bouquet of Thyme"], + + "tentudia": ["Tentudia's Carnal Remains", + "Remains of Tentudia's Hair", + "Tentudia's Skeletal Remains"], + + "egg" : ["Melted Golden Coins", + "Torn Bridal Ribbon", + "Black Grieving Veil"], + + "bones" : ["Parietal bone of Lasser, the Inquisitor", + "Jaw of Ashgan, the Inquisitor", + "Cervical vertebra of Zicher, the Brewmaster", + "Clavicle of Dalhuisen, the Schoolchild", + "Sternum of Vitas, the Performer", + "Ribs of Sabnock, the Guardian", + "Vertebra of John, the Gambler", + "Scapula of Carlos, the Executioner", + "Humerus of McMittens, the Nurse", + "Ulna of Koke, the Troubadour", + "Radius of Helzer, the Poet", + "Frontal of Martinus, the Ropemaker", + "Metacarpus of Hodges, the Blacksmith", + "Phalanx of Arthur, the Sailor", + "Phalanx of Miriam, the Counsellor", + "Phalanx of Brannon, the Gravedigger", + "Coxal of June, the Prostitute", + "Sacrum of the Dark Warlock", + "Coccyx of Daniel, the Possessed", + "Femur of Karpow, the Bounty Hunter", + "Kneecap of Sebastien, the Puppeteer", + "Tibia of Alsahli, the Mystic", + "Fibula of Rysp, the Ranger", + "Temporal of Joel, the Thief", + "Metatarsus of Rikusyo, the Traveller", + "Phalanx of Zeth, the Prisoner", + "Phalanx of William, the Sceptic", + "Phalanx of Aralcarim, the Archivist", + "Occipital of Tequila, the Metalsmith", + "Maxilla of Tarradax, the Cleric", + "Nasal bone of Charles, the Artist", + "Hyoid bone of Senex, the Beggar", + "Vertebra of Lindquist, the Forger", + "Trapezium of Jeremiah, the Hangman", + "Trapezoid of Yeager, the Jeweller", + "Capitate of Barock, the Herald", + "Hamate of Vukelich, the Copyist", + "Pisiform of Hernandez, the Explorer", + "Triquetral of Luca, the Tailor", + "Lunate of Keiya, the Butcher", + "Scaphoid of Fierce, the Leper", + "Anklebone of Weston, the Pilgrim", + "Calcaneum of Persian, the Bandit", + "Navicular of Kahnnyhoo, the Murderer"], + + "power" : ["Life Upgrade", + "Fervour Upgrade", + "Empty Bile Vessel", + "Quicksilver"], + + "prayer" : ["Seguiriya to your Eyes like Stars", + "Debla of the Lights", + "Saeta Dolorosa", + "Campanillero to the Sons of the Aurora", + "Lorquiana", + "Zarabanda of the Safe Haven", + "Taranto to my Sister", + "Solea of Excommunication", + "Tiento to your Thorned Hairs", + "Cante Jondo of the Three Sisters", + "Verdiales of the Forsaken Hamlet", + "Romance to the Crimson Mist", + "Zambra to the Resplendent Crown", + "Cantina of the Blue Rose", + "Mirabras of the Return to Port"] +} + +tears_set: Set[str] = [ + "Tears of Atonement (500)", + "Tears of Atonement (625)", + "Tears of Atonement (750)", + "Tears of Atonement (1000)", + "Tears of Atonement (1250)", + "Tears of Atonement (1500)", + "Tears of Atonement (1750)", + "Tears of Atonement (2000)", + "Tears of Atonement (2100)", + "Tears of Atonement (2500)", + "Tears of Atonement (2600)", + "Tears of Atonement (3000)", + "Tears of Atonement (4300)", + "Tears of Atonement (5000)", + "Tears of Atonement (5500)", + "Tears of Atonement (9000)", + "Tears of Atonement (10000)", + "Tears of Atonement (11250)", + "Tears of Atonement (18000)", + "Tears of Atonement (30000)" +] + +reliquary_set: Set[str] = [ + "Reliquary of the Fervent Heart", + "Reliquary of the Suffering Heart", + "Reliquary of the Sorrowful Heart" +] + +skill_set: Set[str] = [ + "Combo Skill", + "Charged Skill", + "Ranged Skill", + "Dive Skill", + "Lunge Skill" +] \ No newline at end of file diff --git a/worlds/blasphemous/Locations.py b/worlds/blasphemous/Locations.py new file mode 100644 index 00000000..88065de4 --- /dev/null +++ b/worlds/blasphemous/Locations.py @@ -0,0 +1,1295 @@ +from typing import List, Set, TypedDict + + +class LocationDict(TypedDict): + name: str + region: str + game_id: str + room: str + + +location_table: List[LocationDict] = [ + # Albero (35) + {'name': "Albero: Tirso's house, top floor", + 'region': "albero", + 'game_id': "RB01", + 'room': "D01Z02S02"}, + {'name': "Albero: Outside Ossuary", + 'region': "albero", + 'game_id': "CO43", + 'room': "D01Z02S04"}, + {'name': "Albero: Graveyard", + 'region': "albero", + 'game_id': "CO16", + 'room': "D01Z02S05"}, + {'name': "Albero: Gate of Travel room", + 'region': "albero", + 'game_id': "QI65", + 'room': "D01Z02S07"}, + {'name': "Albero: Child of Moonlight", + 'region': "albero", + 'game_id': "RESCUED_CHERUB_08", + 'room': "D01Z02S03"}, + {'name': "Albero: Bless Linen Cloth", + 'region': "albero", + 'game_id': "RE04", + 'room': "D01Z02S01"}, + {'name': "Albero: Bless Hatched Egg", + 'region': "albero", + 'game_id': "RE10", + 'room': "D01Z02S01"}, + {'name': "Albero: Bless Severed Hand", + 'region': "albero", + 'game_id': "RE02", + 'room': "D01Z02S01"}, + {'name': "Albero: First gift for Cleofas", + 'region': "albero", + 'game_id': "QI01", + 'room': "D01Z02S03"}, + {'name': "Albero: Final gift for Cleofas", + 'region': "albero", + 'game_id': "PR11", + 'room': "D01Z02S03"}, + {'name': "Albero: Tirso's 1st reward", + 'region': "albero", + 'game_id': "QI66", + 'room': "D01Z02S02"}, + {'name': "Albero: Tirso's 2nd reward", + 'region': "albero", + 'game_id': "Tirso[500]", + 'room': "D01Z02S02"}, + {'name': "Albero: Tirso's 3rd reward", + 'region': "albero", + 'game_id': "Tirso[1000]", + 'room': "D01Z02S02"}, + {'name': "Albero: Tirso's 4th reward", + 'region': "albero", + 'game_id': "Tirso[2000]", + 'room': "D01Z02S02"}, + {'name': "Albero: Tirso's 5th reward", + 'region': "albero", + 'game_id': "Tirso[5000]", + 'room': "D01Z02S02"}, + {'name': "Albero: Tirso's 6th reward", + 'region': "albero", + 'game_id': "Tirso[10000]", + 'room': "D01Z02S02"}, + {'name': "Albero: Tirso's final reward", + 'region': "albero", + 'game_id': "QI56", + 'room': "D01Z02S02"}, + {'name': "Albero: Lvdovico's 1st reward", + 'region': "albero", + 'game_id': "Lvdovico[500]", + 'room': "D01Z02S03"}, + {'name': "Albero: Lvdovico's 2nd reward", + 'region': "albero", + 'game_id': "Lvdovico[1000]", + 'room': "D01Z02S03"}, + {'name': "Albero: Lvdovico's 3rd reward", + 'region': "albero", + 'game_id': "PR03", + 'room': "D01Z02S03"}, + {'name': "Ossuary: Isidora, Voice of the Dead", + 'region': "albero", + 'game_id': "QI201", + 'room': "D01BZ08S01"}, + {'name': "Albero: Mea Culpa altar", + 'region': "albero", + 'game_id': "Sword[D01Z02S06]", + 'room': "D01Z02S06"}, + {'name': "Albero: Donate 5000 Tears", + 'region': "albero", + 'game_id': "RB104", + 'room': "D01BZ04S01"}, + {'name': "Albero: Donate 50000 Tears", + 'region': "albero", + 'game_id': "RB105", + 'room': "D01BZ04S01"}, + {'name': "Ossuary: 1st reward", + 'region': "albero", + 'game_id': "Undertaker[250]", + 'room': "D01BZ06S01"}, + {'name': "Ossuary: 2nd reward", + 'region': "albero", + 'game_id': "Undertaker[500]", + 'room': "D01BZ06S01"}, + {'name': "Ossuary: 3rd reward", + 'region': "albero", + 'game_id': "Undertaker[750]", + 'room': "D01BZ06S01"}, + {'name': "Ossuary: 4th reward", + 'region': "albero", + 'game_id': "Undertaker[1000]", + 'room': "D01BZ06S01"}, + {'name': "Ossuary: 5th reward", + 'region': "albero", + 'game_id': "Undertaker[1250]", + 'room': "D01BZ06S01"}, + {'name': "Ossuary: 6th reward", + 'region': "albero", + 'game_id': "Undertaker[1500]", + 'room': "D01BZ06S01"}, + {'name': "Ossuary: 7th reward", + 'region': "albero", + 'game_id': "Undertaker[1750]", + 'room': "D01BZ06S01"}, + {'name': "Ossuary: 8th reward", + 'region': "albero", + 'game_id': "Undertaker[2000]", + 'room': "D01BZ06S01"}, + {'name': "Ossuary: 9th reward", + 'region': "albero", + 'game_id': "Undertaker[2500]", + 'room': "D01BZ06S01"}, + {'name': "Ossuary: 10th reward", + 'region': "albero", + 'game_id': "Undertaker[3000]", + 'room': "D01BZ06S01"}, + {'name': "Ossuary: 11th reward", + 'region': "albero", + 'game_id': "Undertaker[5000]", + 'room': "D01BZ06S01"}, + + # All the Tears of the Sea (1) + {'name': "AtTotS: Miriam's gift", + 'region': "attots", + 'game_id': "PR201", + 'room': "D04Z04S02"}, + + # Archcathedral Rooftops (11) + {'name': "AR: First soldier fight", + 'region': "ar", + 'game_id': "QI02", + 'room': "D06Z01S03"}, + {'name': "AR: Second soldier fight", + 'region': "ar", + 'game_id': "QI03", + 'room': "D06Z01S06"}, + {'name': "AR: Third soldier fight", + 'region': "ar", + 'game_id': "QI04", + 'room': "D06Z01S21"}, + {'name': "AR: Upper west shaft ledge", + 'region': "ar", + 'game_id': "CO06", + 'room': "D06Z01S12"}, + {'name': "AR: Upper west shaft Child of Moonlight", + 'region': "ar", + 'game_id': "RESCUED_CHERUB_36", + 'room': "D06Z01S12"}, + {'name': "AR: Upper west shaft chest", + 'region': "ar", + 'game_id': "PR12", + 'room': "D06Z01S12"}, + {'name': "AR: Statue near MoM", + 'region': "ar", + 'game_id': "HE04", + 'room': "D06Z01S22"}, + {'name': "AR: Lady of the Six Sorrows", + 'region': "ar", + 'game_id': "Lady[D06Z01S24]", + 'room': "D06Z01S24"}, + {'name': "AR: Upper east shaft ledge", + 'region': "ar", + 'game_id': "CO40", + 'room': "D06Z01S15"}, + {'name': "AR: Mea Culpa altar", + 'region': "ar", + 'game_id': "Sword[D06Z01S11]", + 'room': "D06Z01S11"}, + {'name': "AR: Crisanta of the Wrapped Agony", + 'region': "ar", + 'game_id': "BS16", + 'room': "D06Z01S25"}, + + # Bridge of the Three Cavalries (3) + {'name': "BotTC: Esdras, of the Anointed Legion", + 'region': "bottc", + 'game_id': "BS12", + 'room': "D08Z01S01"}, + {'name': "BotTC: Esdras' gift", + 'region': "bottc", + 'game_id': "PR09", + 'room': "D08Z01S01"}, + {'name': "BotTC: Inside giant statue", + 'region': "bottc", + 'game_id': "HE101", + 'room': "D08Z01S02"}, + + # Brotherhood of the Silent Sorrow (11) + {'name': "BotSS: Beginning gift", + 'region': "botss", + 'game_id': "QI106", + 'room': "D17Z01S01"}, + {'name': "BotSS: Starting room Child of Moonlight", + 'region': "botss", + 'game_id': "RESCUED_CHERUB_06", + 'room': "D17Z01S01"}, + {'name': "BotSS: Starting room ledge", + 'region': "botss", + 'game_id': "RB204", + 'room': "D17Z01S01"}, + {'name': "BotSS: Chamber of the Eldest Brother", + 'region': "botss", + 'game_id': "RE01", + 'room': "D17BZ01S01[relic]"}, + {'name': "BotSS: Mea Culpa altar", + 'region': "botss", + 'game_id': "Sword[D17Z01S08]", + 'room': "D17Z01S08"}, + {'name': "BotSS: Platforming gauntlet", + 'region': "botss", + 'game_id': "CO25", + 'room': "D17Z01S04"}, + {'name': "BotSS: Blue candle", + 'region': "botss", + 'game_id': "RB25", + 'room': "D17Z01S04"}, + {'name': "BotSS: Outside church", + 'region': "botss", + 'game_id': "PR203", + 'room': "D17Z01S14"}, + {'name': "BotSS: Esdras' final gift", + 'region': "botss", + 'game_id': "QI204", + 'room': "D17Z01S15"}, + {'name': "BotSS: Crisanta's gift", + 'region': "botss", + 'game_id': "QI301", + 'room': "D17Z01S15"}, + {'name': "BotSS: Warden of the Silent Sorrow", + 'region': "botss", + 'game_id': "BS13", + 'room': "D17Z01S11"}, + + # Convent of Our Lady of the Charred Visage (13) + {'name': "CoOLotCV: Snowy window ledge", + 'region': "coolotcv", + 'game_id': "CO05", + 'room': "D02Z03S03"}, + {'name': "CoOLotCV: Center enemy lineup", + 'region': "coolotcv", + 'game_id': "CO15", + 'room': "D02Z03S07"}, + {'name': "CoOLotCV: Center miasma room", + 'region': "coolotcv", + 'game_id': "RB08", + 'room': "D02Z03S05"}, + {'name': "CoOLotCV: Lower west statue", + 'region': "coolotcv", + 'game_id': "HE03", + 'room': "D02Z03S12"}, + {'name': "CoOLotCV: Lady of the Six Sorrows", + 'region': "coolotcv", + 'game_id': "Lady[D02Z03S15]", + 'room': "D02Z03S15"}, + {'name': "CoOLotCV: Mea Culpa altar", + 'region': "coolotcv", + 'game_id': "Sword[D02Z03S13]", + 'room': "D02Z03S13"}, + {'name': "CoOLotCV: Red candle", + 'region': "coolotcv", + 'game_id': "RB18", + 'room': "D02Z03S06"}, + {'name': "CoOLotCV: Blue candle", + 'region': "coolotcv", + 'game_id': "RB24", + 'room': "D02Z03S17"}, + {'name': "CoOLotCV: Outside pathway", + 'region': "coolotcv", + 'game_id': "RB107", + 'room': "D02Z03S23"}, + {'name': "CoOLotCV: Fountain of burning oil", + 'region': "coolotcv", + 'game_id': "QI57", + 'room': "D02Z03S21"}, + {'name': "CoOLotCV: Our Lady of the Charred Visage", + 'region': "coolotcv", + 'game_id': "BS03", + 'room': "D02Z03S20"}, + {'name': "CoOLotCV: Visage of Compunction", + 'region': "coolotcv", + 'game_id': "QI40", + 'room': "D02Z03S21"}, + {'name': "CoOLotCV: Mask room", + 'region': "coolotcv", + 'game_id': "QI61", + 'room': "D02Z03S19"}, + + # Deambulatory of His Holiness (3) + {'name': "DoHH: Viridiana's gift", + 'region': "dohh", + 'game_id': "PR08", + 'room': "D07Z01S01"}, + + # Desecrated Cistern (20) + {'name': "DC: Lady of the Six Sorrows, from MD", + 'region': "dc", + 'game_id': "Lady[D01Z05S22]", + 'room': "D01Z05S22"}, + {'name': "DC: Behind sewage drips", + 'region': "dc", + 'game_id': "CO41", + 'room': "D01Z05S15"}, + {'name': "DC: Child of Moonlight, above water", + 'region': "dc", + 'game_id': "RESCUED_CHERUB_11", + 'room': "D01Z05S14"}, + {'name': "DC: Lower east tunnel chest", + 'region': "dc", + 'game_id': "QI45", + 'room': "D01Z05S11"}, + {'name': "DC: Upper east tunnel chest", + 'region': "dc", + 'game_id': "PR16", + 'room': "D01Z05S06"}, + {'name': "DC: Upper east Child of Moonlight", + 'region': "dc", + 'game_id': "RESCUED_CHERUB_13", + 'room': "D01Z05S06"}, + {'name': "DC: Hidden alcove near fountain", + 'region': "dc", + 'game_id': "QI67", + 'room': "D01Z05S05"}, + {'name': "DC: Shortcut to WotBC", + 'region': "dc", + 'game_id': "CO09", + 'room': "D01Z05S05"}, + {'name': "DC: Oil of the Pilgrims", + 'region': "dc", + 'game_id': "Oil[D01Z05S07]", + 'room': "D01Z05S07"}, + {'name': "DC: Child of Moonlight, miasma room", + 'region': "dc", + 'game_id': "RESCUED_CHERUB_14", + 'room': "D01Z05S08"}, + {'name': "DC: Behind gate in miasma room", + 'region': "dc", + 'game_id': "QI12", + 'room': "D01Z05S08"}, + {'name': "DC: Child of Moonlight, behind pillar", + 'region': "dc", + 'game_id': "RESCUED_CHERUB_12", + 'room': "D01Z05S13"}, + {'name': "DC: High ledge near elevator shaft", + 'region': "dc", + 'game_id': "CO32", + 'room': "D01Z05S17"}, + {'name': "DC: Shroud puzzle", + 'region': "dc", + 'game_id': "RB03", + 'room': "D01Z05S21"}, + {'name': "DC: Chalice room", + 'region': "dc", + 'game_id': "QI75", + 'room': "D01Z05S23"}, + {'name': "DC: Mea Culpa altar", + 'region': "dc", + 'game_id': "Sword[D01Z05S24]", + 'room': "D01Z05S24"}, + {'name': "DC: Lady of the Six Sorrows, elevator shaft", + 'region': "dc", + 'game_id': "Lady[D01Z05S26]", + 'room': "D01Z05S26"}, + {'name': "DC: Top of elevator Child of Moonlight", + 'region': "dc", + 'game_id': "RESCUED_CHERUB_15", + 'room': "D01Z05S20"}, + {'name': "DC: Elevator shaft Child of Moonlight", + 'region': "dc", + 'game_id': "RESCUED_CHERUB_22", + 'room': "D01Z05S25"}, + {'name': "DC: Elevator shaft ledge", + 'region': "dc", + 'game_id': "CO44", + 'room': "D01Z05S25"}, + + # Echoes of Salt (2) + {'name': "EoS: Lantern jump near MotED", + 'region': "eos", + 'game_id': "RB108", + 'room': "D20Z01S02"}, + {'name': "EoS: Lantern jump near elevator", + 'region': "eos", + 'game_id': "RB202", + 'room': "D20Z01S09"}, + + # Graveyard of the Peaks (21) + {'name': "GotP: Shop cave Child of Moonlight", + 'region': "gotp", + 'game_id': "RESCUED_CHERUB_31", + 'room': "D02Z02S08"}, + {'name': "GotP: Shop cave hidden hole", + 'region': "gotp", + 'game_id': "CO42", + 'room': "D02Z02S08"}, + {'name': "GotP: Shop item 1", + 'region': "gotp", + 'game_id': "QI11", + 'room': "D02BZ01S01"}, + {'name': "GotP: Shop item 2", + 'region': "gotp", + 'game_id': "RB37", + 'room': "D02BZ01S01"}, + {'name': "GotP: Shop item 3", + 'region': "gotp", + 'game_id': "RB02", + 'room': "D02BZ01S01"}, + {'name': "GotP: Confessor Dungeon room", + 'region': "gotp", + 'game_id': "RB38", + 'room': "D02Z02S06"}, + {'name': "GotP: Elevator shaft Child of Moonlight", + 'region': "gotp", + 'game_id': "RESCUED_CHERUB_26", + 'room': "D02Z02S11"}, + {'name': "GotP: Elevator shaft ledge", + 'region': "gotp", + 'game_id': "QI53", + 'room': "D02Z02S11"}, + {'name': "GotP: Lady of the Six Sorrows", + 'region': "gotp", + 'game_id': "Lady[D02Z02S12]", + 'room': "D02Z02S12"}, + {'name': "GotP: Self sacrifice statue", + 'region': "gotp", + 'game_id': "HE11", + 'room': "D02Z02S13"}, + {'name': "GotP: Lower east shaft", + 'region': "gotp", + 'game_id': "QI46", + 'room': "D02Z02S03"}, + {'name': "GotP: Center east shaft", + 'region': "gotp", + 'game_id': "CO29", + 'room': "D02Z02S03"}, + {'name': "GotP: Upper east shaft", + 'region': "gotp", + 'game_id': "QI08", + 'room': "D02Z02S03"}, + {'name': "GotP: East cliffside", + 'region': "gotp", + 'game_id': "RB106", + 'room': "D02Z02S14"}, + {'name': "GotP: West shaft Child of Moonlight", + 'region': "gotp", + 'game_id': "RESCUED_CHERUB_25", + 'room': "D02Z02S04"}, + {'name': "GotP: Lower west shaft", + 'region': "gotp", + 'game_id': "RB32", + 'room': "D02Z02S04"}, + {'name': "GotP: Upper west shaft", + 'region': "gotp", + 'game_id': "CO01", + 'room': "D02Z02S04"}, + {'name': "GotP: Center shaft Child of Moonlight", + 'region': "gotp", + 'game_id': "RESCUED_CHERUB_24", + 'room': "D02Z02S02"}, + {'name': "GotP: Center shaft ledge", + 'region': "gotp", + 'game_id': "RB15", + 'room': "D02Z02S05"}, + {'name': "GotP: Oil of the Pilgrims", + 'region': "gotp", + 'game_id': "Oil[D02Z02S10]", + 'room': "D02Z02S10"}, + {'name': "GotP: Amanecida of the Bejeweled Arrow", + 'region': "gotp", + 'game_id': "D02Z02S14[18000]", + 'room': "D02Z02S14"}, + + # Grievance Ascends (12) + {'name': "GA: Lower west ledge", + 'region': "ga", + 'game_id': "QI44", + 'room': "D03Z03S02"}, + {'name': "GA: Miasma room treasure", + 'region': "ga", + 'game_id': "RE07", + 'room': "D03Z03S06"}, + {'name': "GA: Miasma room Child of Moonlight", + 'region': "ga", + 'game_id': "RESCUED_CHERUB_19", + 'room': "D03Z03S06"}, + {'name': "GA: Miasma room floor", + 'region': "ga", + 'game_id': "CO12", + 'room': "D03Z03S06"}, + {'name': "GA: Oil of the Pilgrims", + 'region': "ga", + 'game_id': "Oil[D03Z03S13]", + 'room': "D03Z03S13"}, + {'name': "GA: End of blood bridge", + 'region': "ga", + 'game_id': "QI10", + 'room': "D03Z03S08"}, + {'name': "GA: Blood bridge Child of Moonlight", + 'region': "ga", + 'game_id': "RESCUED_CHERUB_21", + 'room': "D03Z03S08"}, + {'name': "GA: Lower east Child of Moonlight", + 'region': "ga", + 'game_id': "RESCUED_CHERUB_20", + 'room': "D03Z03S09"}, + {'name': "GA: Altasgracias' gift", + 'region': "ga", + 'game_id': "QI13", + 'room': "D03Z03S10"}, + {'name': "GA: Empty giant egg", + 'region': "ga", + 'game_id': "RB06", + 'room': "D03Z03S10"}, + {'name': "GA: Tres Angustias", + 'region': "ga", + 'game_id': "BS04", + 'room': "D03Z03S15"}, + {'name': "GA: Visage of Contrition", + 'region': "ga", + 'game_id': "QI39", + 'room': "D03Z03S16"}, + + # Hall of the Dawning (2) + {'name': "HotD: Mirror room", + 'region': "hotd", + 'game_id': "QI105", + 'room': "D08Z02S01"}, + {'name': "HotD: Laudes, the First of the Amanecidas", + 'region': "hotd", + 'game_id': "LaudesBossTrigger[30000]", + 'room': "D08Z02S03"}, + + # Jondo (13) + {'name': "Jondo: Upper east ledge", + 'region': "jondo", + 'game_id': "CO08", + 'room': "D03Z03S01"}, + {'name': "Jondo: Upper east chest", + 'region': "jondo", + 'game_id': "PR10", + 'room': "D03Z03S01"}, + {'name': "Jondo: Lower east under chargers", + 'region': "jondo", + 'game_id': "CO33", + 'room': "D03Z03S04"}, + {'name': "Jondo: Lower east bell trap", + 'region': "jondo", + 'game_id': "QI19", + 'room': "D03Z03S06"}, + {'name': "Jondo: Upper east Child of Moonlight", + 'region': "jondo", + 'game_id': "RESCUED_CHERUB_18", + 'room': "D03Z03S05"}, + {'name': "Jondo: Spike tunnel Child of Moonlight", + 'region': "jondo", + 'game_id': "RESCUED_CHERUB_37", + 'room': "D03Z03S11"}, + {'name': "Jondo: Spike tunnel statue", + 'region': "jondo", + 'game_id': "HE06", + 'room': "D03Z03S11"}, + {'name': "Jondo: Spike tunnel cave", + 'region': "jondo", + 'game_id': "QI103", + 'room': "D03Z03S15"}, + {'name': "Jondo: Lower west lift alcove", + 'region': "jondo", + 'game_id': "CO07", + 'room': "D03Z03S07"}, + {'name': "Jondo: Lower west bell alcove", + 'region': "jondo", + 'game_id': "QI41", + 'room': "D03Z03S08"}, + {'name': "Jondo: Upper west bell puzzle", + 'region': "jondo", + 'game_id': "QI52", + 'room': "D03Z03S12"}, + {'name': "Jondo: Upper west tree root", + 'region': "jondo", + 'game_id': "RB28", + 'room': "D03Z03S13"}, + {'name': "Jondo: Upper west Child of Moonlight", + 'region': "jondo", + 'game_id': "RESCUED_CHERUB_17", + 'room': "D03Z03S10"}, + + # Knot of the Three Words (1) + {'name': "KotTW: Gift from the Traitor", + 'region': "kottw", + 'game_id': "HE201", + 'room': "D04Z03S02"}, + + # Library of the Negated Words (18) + {'name': "LotNW: Platform room Child of Moonlight", + 'region': "lotnw", + 'game_id': "RESCUED_CHERUB_01", + 'room': "D05Z01S04"}, + {'name': "LotNW: Platform room ledge", + 'region': "lotnw", + 'game_id': "CO18", + 'room': "D05Z01S04"}, + {'name': "LotNW: Root ceiling platform", + 'region': "lotnw", + 'game_id': "CO22", + 'room': "D05Z01S05"}, + {'name': "LotNW: Hidden floor", + 'region': "lotnw", + 'game_id': "QI50", + 'room': "D05Z01S05"}, + {'name': "LotNW: Miasma hallway chest", + 'region': "lotnw", + 'game_id': "RB31", + 'room': "D05Z01S06"}, + {'name': "LotNW: Lady of the Six Sorrows", + 'region': "lotnw", + 'game_id': "Lady[D05Z01S14]", + 'room': "D05Z01S14"}, + {'name': "LotNW: Bone puzzle", + 'region': "lotnw", + 'game_id': "PR15", + 'room': "D05Z01S18"}, + {'name': "LotNW: Lowest west upper ledge", + 'region': "lotnw", + 'game_id': "CO28", + 'room': "D05Z01S11"}, + {'name': "LotNW: Platform puzzle chest", + 'region': "lotnw", + 'game_id': "PR07", + 'room': "D05Z01S10"}, + {'name': "LotNW: Lowest west center ledge", + 'region': "lotnw", + 'game_id': "RB30", + 'room': "D05Z01S11"}, + {'name': "LotNW: Lowest west Child of Moonlight", + 'region': "lotnw", + 'game_id': "RESCUED_CHERUB_02", + 'room': "D05Z01S11"}, + {'name': "LotNW: Oil of the Pilgrims", + 'region': "lotnw", + 'game_id': "Oil[D05Z01S19]", + 'room': "D05Z01S19"}, + {'name': "LotNW: Elevator Child of Moonlight", + 'region': "lotnw", + 'game_id': "RESCUED_CHERUB_32", + 'room': "D05Z01S21"}, + {'name': "LotNW: Mask room", + 'region': "lotnw", + 'game_id': "QI62", + 'room': "D05Z01S15"}, + {'name': "LotNW: Mea Culpa altar", + 'region': "lotnw", + 'game_id': "Sword[D05Z01S13]", + 'room': "D05Z01S13"}, + {'name': "LotNW: Red candle", + 'region': "lotnw", + 'game_id': "RB19", + 'room': "D05Z01S02"}, + {'name': "LotNW: Silence for Diosdado", + 'region': "lotnw", + 'game_id': "RB203", + 'room': "D05Z01S11"}, # ? + {'name': "LotNW: Twisted wood hidden wall", + 'region': "lotnw", + 'game_id': "RB301", + 'room': "D05BZ01S01"}, + + # Mercy Dreams (15) + {'name': "MD: First area hidden wall", + 'region': "md", + 'game_id': "CO30", + 'room': "D01Z04S05"}, + {'name': "MD: Second area trapped chest", + 'region': "md", + 'game_id': "PR01", + 'room': "D01Z04S07"}, + {'name': "MD: Second area ledge", + 'region': "md", + 'game_id': "CO03", + 'room': "D01Z04S06"}, + {'name': "MD: Second area Child of Moonlight", + 'region': "md", + 'game_id': "RESCUED_CHERUB_09", + 'room': "D01Z04S06"}, + {'name': "MD: Red candle", + 'region': "md", + 'game_id': "RB17", + 'room': "D01Z04S08"}, + {'name': "MD: Shop item 1", + 'region': "md", + 'game_id': "QI58", + 'room': "D01BZ02S01"}, + {'name': "MD: Shop item 2", + 'region': "md", + 'game_id': "RB05", + 'room': "D01BZ02S01"}, + {'name': "MD: Shop item 3", + 'region': "md", + 'game_id': "RB09", + 'room': "D01BZ02S01"}, + {'name': "MD: Third area hidden room", + 'region': "md", + 'game_id': "QI48", + 'room': "D01Z04S11"}, + {'name': "MD: Sliding challenge", + 'region': "md", + 'game_id': "CO38", + 'room': "D01Z04S14"}, + {'name': "MD: Ten Piedad", + 'region': "md", + 'game_id': "BS01", + 'room': "D01Z04S18"}, + {'name': "MD: Visage of Attrition", + 'region': "md", + 'game_id': "QI38", + 'room': "D01Z04S19"}, + {'name': "MD: Blue candle", + 'region': "md", + 'game_id': "RB26", + 'room': "D01Z04S16"}, + {'name': "MD: Cave Child of Moonlight", + 'region': "md", + 'game_id': "RESCUED_CHERUB_33", + 'room': "D01Z04S16"}, + {'name': "MD: Behind gate to TSC", + 'region': "md", + 'game_id': "CO21", + 'room': "D01Z04S13"}, + + # Mother of Mothers (14) + {'name': "MoM: Oil of the Pilgrims", + 'region': "mom", + 'game_id': "Oil[D04Z02S14]", + 'room': "D04Z02S14"}, + {'name': "MoM: Upper east ledge", + 'region': "mom", + 'game_id': "RB33", + 'room': "D04Z02S07"}, + {'name': "MoM: East chandelier platform", + 'region': "mom", + 'game_id': "CO35", + 'room': "D04Z02S"}, + {'name': "MoM: Lower west Child of Moonlight", + 'region': "mom", + 'game_id': "RESCUED_CHERUB_30", + 'room': ""}, + {'name': "MoM: Upper west floor", + 'region': "mom", + 'game_id': "CO17", + 'room': "D04Z02S02"}, + {'name': "MoM: Redento's treasure", + 'region': "mom", + 'game_id': "RE03", + 'room': "D04BZ02S01"}, + {'name': "MoM: Final meeting with Redento", + 'region': "mom", + 'game_id': "QI54", + 'room': "D04BZ02S01"}, + {'name': "MoM: Giant chandelier statue", + 'region': "mom", + 'game_id': "HE01", + 'room': "D04Z02S16"}, + {'name': "MoM: Outside Cleofas' room", + 'region': "mom", + 'game_id': "CO34", + 'room': "D04Z02S06"}, + {'name': "MoM: Upper center floor", + 'region': "mom", + 'game_id': "CO20", + 'room': "D04Z02S11"}, + {'name': "MoM: Upper center Child of Moonlight", + 'region': "mom", + 'game_id': "RESCUED_CHERUB_29", + 'room': ""}, + {'name': "MoM: Mea Culpa altar", + 'region': "mom", + 'game_id': "Sword[D04Z02S12]", + 'room': "D04Z02S12"}, + {'name': "MoM: Melquiades, The Exhumed Archbishop", + 'region': "mom", + 'game_id': "BS05", + 'room': "D04Z02S22"}, + {'name': "MoM: Mask room", + 'region': "mom", + 'game_id': "QI60", + 'room': "D04Z02S15"}, + + # Mountains of the Endless Dusk (8) + {'name': "MotED: Under entrance to DC", + 'region': "moted", + 'game_id': "CO13", + 'room': "D03Z01S01"}, + {'name': "MotED: Perpetva", + 'region': "moted", + 'game_id': "RB13", + 'room': "D03Z01S06"}, + {'name': "MotED: Child of Moonlight, above chasm", + 'region': "moted", + 'game_id': "RESCUED_CHERUB_16", + 'room': "D03Z01S03"}, + {'name': "MotED: Platform above chasm", + 'region': "moted", + 'game_id': "QI47", + 'room': "D03Z01S03"}, + {'name': "MotED: 1st meeting with Redento", + 'region': "moted", + 'game_id': "RB22", + 'room': "D03Z01S03"}, + {'name': "MotED: Blood platform alcove", + 'region': "moted", + 'game_id': "QI63", + 'room': "D03Z01S04"}, + {'name': "MotED: Egg hatching", + 'region': "moted", + 'game_id': "QI14", + 'room': "D03Z01S06"}, + {'name': "MotED: Amanecida of the Golden Blades", + 'region': "moted", + 'game_id': "D03Z01S03[18000]", + 'room': "D03Z01S03"}, + + # Mourning and Havoc (4) + {'name': "MaH: West chest", + 'region': "mah", + 'game_id': "PR202", + 'room': "D20Z02S11"}, + {'name': "MaH: Upper east chest", + 'region': "mah", + 'game_id': "RB201", + 'room': "D20Z02S02"}, + {'name': "MaH: Sierpes' eye", + 'region': "mah", + 'game_id': "QI202", + 'room': "D20Z02S08"}, + {'name': "MaH: Sierpes", + 'region': "mah", + 'game_id': "BossTrigger[5000]", + 'room': "D20Z02S08"}, + + # Patio of the Silent Steps (9) + {'name': "PotSS: First area Child of Moonlight", + 'region': "potss", + 'game_id': "RESCUED_CHERUB_35", + 'room': "D04Z01S01"}, + {'name': "PotSS: First area ledge", + 'region': "potss", + 'game_id': "CO23", + 'room': "D04Z01S01"}, + {'name': "PotSS: Second area ledge", + 'region': "potss", + 'game_id': "RB14", + 'room': "D04Z01S02"}, + {'name': "PotSS: Third area Child of Moonlight", + 'region': "potss", + 'game_id': "RESCUED_CHERUB_28", + 'room': "D04Z01S03"}, + {'name': "PotSS: Third area lower ledge", + 'region': "potss", + 'game_id': "QI37", + 'room': "D04Z01S03"}, + {'name': "PotSS: Third area upper ledge", + 'region': "potss", + 'game_id': "CO39", + 'room': "D04Z01S03"}, + {'name': "PotSS: Climb to WotHP", + 'region': "potss", + 'game_id': "QI102", + 'room': "D04Z01S05"}, + {'name': "PotSS: 4th meeting with Redento", + 'region': "potss", + 'game_id': "RB21", + 'room': "D04Z01S01"}, + {'name': "PotSS: Amanecida of the Chiselled Steel", + 'region': "potss", + 'game_id': "D04Z01S04[18000]", + 'room': "D04Z01S04"}, + + # Petrous (1) + {'name': "Petrous: Temple entrance", + 'region': "petrous", + 'game_id': "QI101", + 'room': "D01Z06S01"}, + + # The Resting Place of the Sister (1) + {'name': "TRPotS: Perpetva's shrine", + 'region': "trpots", + 'game_id': "QI203", + 'room': "D20Z03S01"}, + + # The Sleeping Canvases (10) + {'name': "TSC: Painting ladder ledge", + 'region': "tsc", + 'game_id': "QI64", + 'room': "D05Z02S02"}, + {'name': "TSC: Candle wax puzzle", + 'region': "tsc", + 'game_id': "HE07", + 'room': "D05Z02S08"}, + {'name': "TSC: Shop item 1", + 'region': "tsc", + 'game_id': "RB12", + 'room': "D05BZ02S01"}, + {'name': "TSC: Shop item 2", + 'region': "tsc", + 'game_id': "QI49", + 'room': "D05BZ02S01"}, + {'name': "TSC: Shop item 3", + 'region': "tsc", + 'game_id': "QI71", + 'room': "D05BZ02S01"}, + {'name': "TSC: Swinging blade tunnel", + 'region': "tsc", + 'game_id': "QI104", + 'room': "D05Z02S15"}, + {'name': "TSC: Exposito, Scion of Abjuration", + 'region': "tsc", + 'game_id': "BS06", + 'room': "D05Z02S14"}, + {'name': "TSC: Under elevator shaft", + 'region': "tsc", + 'game_id': "CO31", + 'room': "D05Z02S11"}, + {'name': "TSC: Jocinero's 1st reward", + 'region': "tsc", + 'game_id': "RE05", + 'room': "D05Z02S10"}, # ? + {'name': "TSC: Jocinero's final reward", + 'region': "tsc", + 'game_id': "PR05", + 'room': "D05Z02S10"}, # ? + + # The Holy Line (6) + {'name': "THL: Deogracias' gift", + 'region': "thl", + 'game_id': "QI31", + 'room': "D01Z01S07"}, + {'name': "THL: Hanging skeleton", + 'region': "thl", + 'game_id': "PR14", + 'room': "D01Z01S02"}, + {'name': "THL: Across blood platforms", + 'region': "thl", + 'game_id': "RB07", + 'room': "D01Z01S02"}, + {'name': "THL: Child of Moonlight", + 'region': "thl", + 'game_id': "RESCUED_CHERUB_07", + 'room': "D01Z01S03"}, + {'name': "THL: Underground ledge", + 'region': "thl", + 'game_id': "CO04", + 'room': "D01Z01S03"}, + {'name': "THL: Underground chest", + 'region': "thl", + 'game_id': "QI55", + 'room': "D01Z01S03"}, + + # Wall of the Holy Prohibitions (19) + {'name': "WotHP: Upper east room, lift puzzle", + 'region': "wothp", + 'game_id': "RB11", + 'room': "D09Z01S02"}, + {'name': "WotHP: Upper east room, center cell ledge", + 'region': "wothp", + 'game_id': "CO10", + 'room': "D09BZ01S01[Cell22]"}, + {'name': "WotHP: Upper east room, center cell floor", + 'region': "wothp", + 'game_id': "QI69", + 'room': "D09BZ01S01[Cell22]"}, + {'name': "WotHP: Upper east room, top bronze cell", + 'region': "wothp", + 'game_id': "RESCUED_CHERUB_03", + 'room': "D09BZ01S01[Cell1]"}, + {'name': "WotHP: Upper east room, top silver cell", + 'region': "wothp", + 'game_id': "CO24", + 'room': "D09BZ01S01[Cell6]"}, + {'name': "WotHP: Upper east room, center gold cell", + 'region': "wothp", + 'game_id': "QI51", + 'room': "D09Z01S02"}, + {'name': "WotHP: Upper west room, center gold cell", + 'region': "wothp", + 'game_id': "CO26", + 'room': "D09BZ01S01[Cell16]"}, + {'name': "WotHP: Lower west room, bottom gold cell", + 'region': "wothp", + 'game_id': "CO02", + 'room': "D09BZ01S01[Cell21]"}, + {'name': "WotHP: Upper west room, top silver cell", + 'region': "wothp", + 'game_id': "RESCUED_CHERUB_34", + 'room': "D09BZ01S01[Cell17~18]"}, # ? + {'name': "WotHP: Lower west room, top ledge", + 'region': "wothp", + 'game_id': "RB16", + 'room': "D09BZ01S01[Cell24]"}, + {'name': "WotHP: Lower east room, hidden ledge", + 'region': "wothp", + 'game_id': "CO27", + 'room': "D09Z01S10"}, + {'name': "WotHP: Lower east room, bottom silver cell", + 'region': "wothp", + 'game_id': "RESCUED_CHERUB_04", + 'room': "D09BZ01S01[Cell11]"}, + {'name': "WotHP: Lower east room, top bronze cell", + 'region': "wothp", + 'game_id': "QI70", + 'room': "D09Z01S10"}, + {'name': "WotHP: Lower east room, top silver cell", + 'region': "wothp", + 'game_id': "CO37", + 'room': "D09BZ01S01[Cell10]"}, + {'name': "WotHP: Outside Child of Moonlight", + 'region': "wothp", + 'game_id': "RESCUED_CHERUB_05", + 'room': "D09Z01S06"}, + {'name': "WotHP: Oil of the Pilgrims", + 'region': "wothp", + 'game_id': "Oil[D09Z01S12]", + 'room': "D09Z01S12"}, + {'name': "WotHP: Quirce, Returned By The Flames", + 'region': "wothp", + 'game_id': "BS14", + 'room': "D09Z01S03"}, + {'name': "WotHP: Collapsing floor ledge", + 'region': "wothp", + 'game_id': "QI72", + 'room': "D09Z01S08"}, + {'name': "WotHP: Amanecida of the Molten Thorn", + 'region': "wothp", + 'game_id': "D09Z01S01[18000]", + 'room': "D09Z01S01"}, + + # Wasteland of the Buried Churches (8) + {'name': "WotBC: Lower log path", + 'region': "wotbc", + 'game_id': "RB04", + 'room': "D01Z03S01"}, + {'name': "WotBC: Hidden alcove", + 'region': "wotbc", + 'game_id': "CO14", + 'room': "D01Z03S02"}, + {'name': "WotBC: Outside ledge", + 'region': "wotbc", + 'game_id': "CO36", + 'room': "D01Z03S03"}, + {'name': "WotBC: Outside Child of Moonlight", + 'region': "wotbc", + 'game_id': "RESCUED_CHERUB_10", + 'room': "D01Z03S03"}, + {'name': "WotBC: Under broken bridge", + 'region': "wotbc", + 'game_id': "QI06", + 'room': "D01Z03S05"}, + {'name': "WotBC: Cliffside statue", + 'region': "wotbc", + 'game_id': "HE02", + 'room': "D01Z03S07"}, + {'name': "WotBC: Cliffside Child of Moonlight", + 'region': "wotbc", + 'game_id': "RESCUED_CHERUB_38", + 'room': "D01Z03S07"}, + {'name': "WotBC: 3rd meeting with Redento", + 'region': "wotbc", + 'game_id': "RB20", + 'room': "D01Z03S01"}, # ? + + # Where Olive Trees Wither (11) + {'name': "WOTW: Below Prie Dieu", + 'region': "wotw", + 'game_id': "CO11", + 'room': "D02Z01S01"}, + {'name': "WOTW: Entrance to tomb", + 'region': "wotw", + 'game_id': "QI20", + 'room': "D02Z01S04"}, + {'name': "WOTW: Gift for the tomb", + 'region': "wotw", + 'game_id': "QI68", + 'room': "D02Z01S"}, + {'name': "WOTW: Underground tomb", + 'region': "wotw", + 'game_id': "PR04", + 'room': "D02Z01S08"}, + {'name': "WOTW: Underground Child of Moonlight", + 'region': "wotw", + 'game_id': "RESCUED_CHERUB_27", + 'room': "D02Z01S06"}, + {'name': "WOTW: Underground ledge", + 'region': "wotw", + 'game_id': "CO19", + 'room': "D02Z01S06"}, + {'name': "WOTW: Upper east Child of Moonlight", + 'region': "wotw", + 'game_id': "RESCUED_CHERUB_23", + 'room': "D02Z01S09"}, + {'name': "WOTW: Upper east statue", + 'region': "wotw", + 'game_id': "HE05", + 'room': "D02Z01S09"}, + {'name': "WOTW: Death run", + 'region': "wotw", + 'game_id': "QI07", + 'room': "D02Z01S05"}, + {'name': "WOTW: Gemino's gift", + 'region': "wotw", + 'game_id': "QI59", + 'room': "D02Z01S01"}, + {'name': "WOTW: Gemino's reward", + 'region': "wotw", + 'game_id': "RB10", + 'room': "D02Z01S01"}, + + # Various (20) + {'name': "Confessor Dungeon 1 extra", + 'region': "dungeon", + 'game_id': "Arena_NailManager[1000]", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 1 main", + 'region': "dungeon", + 'game_id': "QI32", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 2 extra", + 'region': "dungeon", + 'game_id': "HE10", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 2 main", + 'region': "dungeon", + 'game_id': "QI33", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 3 extra", + 'region': "dungeon", + 'game_id': "Arena_NailManager[3000]", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 3 main", + 'region': "dungeon", + 'game_id': "QI34", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 4 extra", + 'region': "dungeon", + 'game_id': "RB34", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 4 main", + 'region': "dungeon", + 'game_id': "QI35", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 5 extra", + 'region': "dungeon", + 'game_id': "Arena_NailManager[5000]", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 5 main", + 'region': "dungeon", + 'game_id': "QI79", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 6 extra", + 'region': "dungeon", + 'game_id': "RB35", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 6 main", + 'region': "dungeon", + 'game_id': "QI80", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 7 extra", + 'region': "dungeon", + 'game_id': "RB36", + 'room': "dungeon"}, + {'name': "Confessor Dungeon 7 main", + 'region': "dungeon", + 'game_id': "QI81", + 'room': "dungeon"}, + {'name': "Defeat 1 Amanecida", + 'region': "dungeon", + 'game_id': "QI107", + 'room': "dungeon"}, + {'name': "Defeat 2 Amanecidas", + 'region': "dungeon", + 'game_id': "QI108", + 'room': "dungeon"}, + {'name': "Defeat 3 Amanecidas", + 'region': "dungeon", + 'game_id': "QI109", + 'room': "dungeon"}, + {'name': "Defeat 4 Amanecidas", + 'region': "dungeon", + 'game_id': "QI110", + 'room': "dungeon"}, + {'name': "Defeat all Amanecidas", + 'region': "dungeon", + 'game_id': "PR101", + 'room': "dungeon"}, + {'name': "Skill 1, Tier 1", + 'region': "dungeon", + 'game_id': "COMBO_1", + 'room': "dungeon"}, + {'name': "Skill 1, Tier 2", + 'region': "dungeon", + 'game_id': "COMBO_2", + 'room': "dungeon"}, + {'name': "Skill 1, Tier 3", + 'region': "dungeon", + 'game_id': "COMBO_3", + 'room': "dungeon"}, + {'name': "Skill 2, Tier 1", + 'region': "dungeon", + 'game_id': "CHARGED_1", + 'room': "dungeon"}, + {'name': "Skill 2, Tier 2", + 'region': "dungeon", + 'game_id': "CHARGED_2", + 'room': "dungeon"}, + {'name': "Skill 2, Tier 3", + 'region': "dungeon", + 'game_id': "CHARGED_3", + 'room': "dungeon"}, + {'name': "Skill 3, Tier 1", + 'region': "dungeon", + 'game_id': "RANGED_1", + 'room': "dungeon"}, + {'name': "Skill 3, Tier 2", + 'region': "dungeon", + 'game_id': "RANGED_2", + 'room': "dungeon"}, + {'name': "Skill 3, Tier 3", + 'region': "dungeon", + 'game_id': "RANGED_3", + 'room': "dungeon"}, + {'name': "Skill 4, Tier 1", + 'region': "dungeon", + 'game_id': "VERTICAL_1", + 'room': "dungeon"}, + {'name': "Skill 4, Tier 2", + 'region': "dungeon", + 'game_id': "VERTICAL_2", + 'room': "dungeon"}, + {'name': "Skill 4, Tier 3", + 'region': "dungeon", + 'game_id': "VERTICAL_3", + 'room': "dungeon"}, + {'name': "Skill 5, Tier 1", + 'region': "dungeon", + 'game_id': "LUNGE_1", + 'room': "dungeon"}, + {'name': "Skill 5, Tier 2", + 'region': "dungeon", + 'game_id': "LUNGE_2", + 'room': "dungeon"}, + {'name': "Skill 5, Tier 3", + 'region': "dungeon", + 'game_id': "LUNGE_3", + 'room': "dungeon"}, +] + +shop_set: Set[str] = [ + "GotP: Shop item 1", + "GotP: Shop item 2", + "GotP: Shop item 3", + "MD: Shop item 1", + "MD: Shop item 2", + "MD: Shop item 3", + "TSC: Shop item 1", + "TSC: Shop item 2", + "TSC: Shop item 3" +] \ No newline at end of file diff --git a/worlds/blasphemous/Options.py b/worlds/blasphemous/Options.py new file mode 100644 index 00000000..be43d8b7 --- /dev/null +++ b/worlds/blasphemous/Options.py @@ -0,0 +1,257 @@ +from Options import Choice, Toggle, DefaultOnToggle, DeathLink + + +class PrieDieuWarp(DefaultOnToggle): + """Automatically unlocks the ability to warp between Prie Dieu shrines.""" + display_name = "Unlock Fast Travel" + + +class SkipCutscenes(DefaultOnToggle): + """Automatically skips most cutscenes.""" + display_name = "Auto Skip Cutscenes" + + +class CorpseHints(DefaultOnToggle): + """Changes the 34 corpses in game to give various hints about item locations.""" + display_name = "Corpse Hints" + + +class Difficulty(Choice): + """Adjusts the logic required to defeat bosses. + Impossible: Removes all logic requirements for bosses. Good luck.""" + display_name = "Difficulty" + option_easy = 0 + option_normal = 1 + option_hard = 2 + option_impossible = 3 + default = 1 + + +class Penitence(Toggle): + """Allows one of the three Penitences to be chosen at the beginning of the game.""" + display_name = "Penitence" + + +class ExpertLogic(Toggle): + """Expands the logic used by the randomizer to allow for some difficult and/or lesser known tricks.""" + display_name = "Expert Logic" + + +class Ending(Choice): + """Choose which ending is required to complete the game.""" + display_name = "Ending" + option_any_ending = 0 + option_ending_b = 1 + option_ending_c = 2 + default = 0 + + +class ThornShuffle(Choice): + """Shuffles the Thorn given by Deogracias and all Thorn upgrades into the item pool.""" + display_name = "Shuffle Thorn" + option_anywhere = 0 + option_local_only = 1 + option_vanilla = 2 + default = 0 + + +class ReliquaryShuffle(DefaultOnToggle): + """Adds the True Torment exclusive Reliquary rosary beads into the item pool.""" + display_name = "Shuffle Penitence Rewards" + + +class CherubShuffle(DefaultOnToggle): + """Shuffles Children of Moonlight into the item pool.""" + display_name = "Shuffle Children of Moonlight" + + +class LifeShuffle(DefaultOnToggle): + """Shuffles life upgrades from the Lady of the Six Sorrows into the item pool.""" + display_name = "Shuffle Life Upgrades" + + +class FervourShuffle(DefaultOnToggle): + """Shuffles fervour upgrades from the Oil of the Pilgrims into the item pool.""" + display_name = "Shuffle Fervour Upgrades" + + +class SwordShuffle(DefaultOnToggle): + """Shuffles Mea Culpa upgrades from the Mea Culpa Altars into the item pool.""" + display_name = "Shuffle Mea Culpa Upgrades" + + +class BlessingShuffle(DefaultOnToggle): + """Shuffles blessings from the Lake of Silent Pilgrims into the item pool.""" + display_name = "Shuffle Blessings" + + +class DungeonShuffle(DefaultOnToggle): + """Shuffles rewards from completing Confessor Dungeons into the item pool.""" + display_name = "Shuffle Dungeon Rewards" + + +class TirsoShuffle(DefaultOnToggle): + """Shuffles rewards from delivering herbs to Tirso into the item pool.""" + display_name = "Shuffle Tirso's Rewards" + + +class MiriamShuffle(DefaultOnToggle): + """Shuffles the prayer given by Miriam into the item pool.""" + display_name = "Shuffle Miriram's Reward" + + +class RedentoShuffle(DefaultOnToggle): + """Shuffles rewards from assisting Redento into the item pool.""" + display_name = "Shuffle Redento's Rewards" + + +class JocineroShuffle(DefaultOnToggle): + """Shuffles rewards from rescuing 20 and 38 Children of Moonlight into the item pool.""" + display_name = "Shuffle Jocinero's Rewards" + + +class AltasgraciasShuffle(DefaultOnToggle): + """Shuffles the reward given by Altasgracias and the item left behind by them into the item pool.""" + display_name = "Shuffle Altasgracias' Rewards" + + +class TentudiaShuffle(DefaultOnToggle): + """Shuffles the rewards from delivering Tentudia's remains to Lvdovico into the item pool.""" + display_name = "Shuffle Lvdovico's Rewards" + + +class GeminoShuffle(DefaultOnToggle): + """Shuffles the rewards from Gemino's quest and the hidden tomb into the item pool.""" + display_name = "Shuffle Gemino's Rewards" + + +class GuiltShuffle(DefaultOnToggle): + """Shuffles the Weight of True Guilt into the item pool.""" + display_name = "Shuffle Immaculate Bead" + + +class OssuaryShuffle(DefaultOnToggle): + """Shuffles the rewards from delivering bones to the Ossuary into the item pool.""" + display_name = "Shuffle Ossuary Rewards" + + +class BossShuffle(DefaultOnToggle): + """Shuffles the Tears of Atonement from defeating bosses into the item pool.""" + display_name = "Shuffle Boss Tears" + + +class WoundShuffle(DefaultOnToggle): + """Shuffles the Holy Wounds required to pass the Bridge of the Three Cavalries into the item pool.""" + display_name = "Shuffle Holy Wounds" + + +class MaskShuffle(DefaultOnToggle): + """Shuffles the masks required to use the elevator in Archcathedral Rooftops into the item pool.""" + display_name = "Shuffle Masks" + + +class EyeShuffle(DefaultOnToggle): + """Shuffles the Eyes of the Traitor from defeating Isidora and Sierpes into the item pool.""" + display_name = "Shuffle Traitor's Eyes" + + +class HerbShuffle(DefaultOnToggle): + """Shuffles the herbs required for Tirso's quest into the item pool.""" + display_name = "Shuffle Herbs" + + +class ChurchShuffle(DefaultOnToggle): + """Shuffles the rewards from donating 5,000 and 50,000 Tears of Atonement to the Church in Albero into the item pool.""" + display_name = "Shuffle Donation Rewards" + + +class ShopShuffle(DefaultOnToggle): + """Shuffles the items sold in Candelaria's shops into the item pool.""" + display_name = "Shuffle Shop Items" + + +class CandleShuffle(DefaultOnToggle): + """Shuffles the Beads of Wax and their upgrades into the item pool.""" + display_name = "Shuffle Candles" + + +class StartWheel(Toggle): + """Changes the beginning gift to The Young Mason's Wheel.""" + display_name = "Start with Wheel" + + +class SkillRando(Toggle): + """Randomizes the abilities from the skill tree into the item pool.""" + display_name = "Skill Randomizer" + + +class EnemyRando(Choice): + """Randomizes the enemies that appear in each room. + Shuffled: Enemies will be shuffled amongst each other, but can only appear as many times as they do in a standard game. + Randomized: Every enemy is completely random, and can appear any number of times. + Some enemies will never be randomized.""" + display_name = "Enemy Randomizer" + option_disabled = 0 + option_shuffled = 1 + option_randomized = 2 + default = 0 + + +class EnemyGroups(DefaultOnToggle): + """Randomized enemies will chosen from sets of specific groups. + (Weak, normal, large, flying) + Has no effect if Enemy Randomizer is disabled.""" + display_name = "Enemy Groups" + + +class EnemyScaling(DefaultOnToggle): + """Randomized enemies will have their stats increased or decreased depending on the area they appear in. + Has no effect if Enemy Randomizer is disabled.""" + display_name = "Enemy Scaling" + + +class BlasphemousDeathLink(DeathLink): + """When you die, everyone dies. The reverse is also true. + Note that Guilt Fragments will not appear when killed by Death Link.""" + + +blasphemous_options = { + "prie_dieu_warp": PrieDieuWarp, + "skip_cutscenes": SkipCutscenes, + "corpse_hints": CorpseHints, + "difficulty": Difficulty, + "penitence": Penitence, + "expert_logic": ExpertLogic, + "ending": Ending, + "thorn_shuffle" : ThornShuffle, + "reliquary_shuffle": ReliquaryShuffle, + "cherub_shuffle" : CherubShuffle, + "life_shuffle" : LifeShuffle, + "fervour_shuffle" : FervourShuffle, + "sword_shuffle" : SwordShuffle, + "blessing_shuffle" : BlessingShuffle, + "dungeon_shuffle" : DungeonShuffle, + "tirso_shuffle" : TirsoShuffle, + "miriam_shuffle" : MiriamShuffle, + "redento_shuffle" : RedentoShuffle, + "jocinero_shuffle" : JocineroShuffle, + "altasgracias_shuffle" : AltasgraciasShuffle, + "tentudia_shuffle" : TentudiaShuffle, + "gemino_shuffle" : GeminoShuffle, + "guilt_shuffle" : GuiltShuffle, + "ossuary_shuffle" : OssuaryShuffle, + "boss_shuffle" : BossShuffle, + "wound_shuffle" : WoundShuffle, + "mask_shuffle" : MaskShuffle, + "eye_shuffle": EyeShuffle, + "herb_shuffle" : HerbShuffle, + "church_shuffle" : ChurchShuffle, + "shop_shuffle" : ShopShuffle, + "candle_shuffle" : CandleShuffle, + "start_wheel": StartWheel, + "skill_randomizer": SkillRando, + "enemy_randomizer": EnemyRando, + "enemy_groups": EnemyGroups, + "enemy_scaling": EnemyScaling, + "death_link": BlasphemousDeathLink +} \ No newline at end of file diff --git a/worlds/blasphemous/Rules.py b/worlds/blasphemous/Rules.py new file mode 100644 index 00000000..6bf4a685 --- /dev/null +++ b/worlds/blasphemous/Rules.py @@ -0,0 +1,1455 @@ +from worlds.generic.Rules import set_rule, add_rule +from ..AutoWorld import LogicMixin + + +class BlasphemousLogic(LogicMixin): + def _blasphemous_blood_relic(self, player): + return self.has("Blood Perpetuated in Sand", player) + + def _blasphemous_water_relic(self, player): + return self.has("Nail Uprooted from Dirt", player) + + def _blasphemous_corpse_relic(self, player): + return self.has("Shroud of Dreamt Sins", player) + + def _blasphemous_fall_relic(self, player): + return self.has("Linen of Golden Thread", player) + + def _blasphemous_miasma_relic(self, player): + return self.has("Silvered Lung of Dolphos", player) + + def _blasphemous_root_relic(self, player): + return self.has("Three Gnarled Tongues", player) + + def _blasphemous_open_holes(self, player): + return self.has_any({"Dive Skill", "Charged Skill"}, player) or \ + self.has_group("prayer", player, 1) or \ + (self.has_any({"Tirana of the Celestial Bastion", "Aubade of the Nameless Guardian"}, player) and \ + self.has("Fervour Upgrade", player, 2)) + + def _blasphemous_bell(self, player): + return self.has("Petrified Bell", player) + + def _blasphemous_bead(self, player): + return self.has("Weight of True Guilt", player) + + def _blasphemous_cloth(self, player): + return self.has("Linen Cloth", player) + + def _blasphemous_pre_egg(self, player): + return self.has("Egg of Deformity", player) + + def _blasphemous_egg(self, player): + return self.has("Hatched Egg of Deformity", player) + + def _blasphemous_hand(self, player): + return self.has("Severed Hand", player) + + def _blasphemous_chalice(self, player): + return self.has("Chalice of Inverted Verses", player) + + def _blasphemous_thimble(self, player): + return self.has("Empty Golden Thimble", player) + + def _blasphemous_full_thimble(self, player): + return self.has("Golden Thimble Filled with Burning Oil", player) + + def _blasphemous_flowers(self, player): + return self.has("Dried Flowers bathed in Tears", player) + + def _blasphemous_redento(self, player): + return self.has_all({"Little Toe made of Limestone", "Big Toe made of Limestone", \ + "Fourth Toe made of Limestone"}, player) and \ + self.has("Knot of Rosary Rope", player) + + def _blasphemous_cord(self, player): + return self.has("Cord of the True Burying", player) + + def _blasphemous_marks(self, player): + return self.has_all({"Mark of the First Refuge", "Mark of the Second Refuge", \ + "Mark of the Third Refuge"}, player) + + def _blasphemous_red_wax(self, player): + return self.has("Bead of Red Wax", player) + + def _blasphemous_blue_wax(self, player): + return self.has("Bead of Blue Wax", player) + + def _blasphemous_both_wax(self, player): + return self.has("Bead of Red Wax", player, 3) and \ + self.has("Bead of Blue Wax", player, 3) + + def _blasphemous_elder_key(self, player): + return self.has("Key to the Chamber of the Eldest Brother", player) + + def _blasphemous_bronze_key(self, player): + return self.has("Key of the Secular", player) + + def _blasphemous_silver_key(self, player): + return self.has("Key of the Scribe", player) + + def _blasphemous_gold_key(self, player): + return self.has("Key of the Inquisitor", player) + + def _blasphemous_high_key(self, player): + return self.has("Key of the High Peaks", player) + + def _blasphemous_wood_key(self, player): + return self.has("Key Grown from Twisted Wood", player) + + def _blasphemous_scapular(self, player): + return self.has("Incomplete Scapular", player) + + def _blasphemous_heart_c(self, player): + return self.has("Apodictic Heart of Mea Culpa", player) + + def _blasphemous_eyes(self, player): + return self.has("Severed Right Eye of the Traitor", player) and \ + self.has("Broken Left Eye of the Traitor", player) + + def _blasphemous_debla(self, player): + return self.has("Debla of the Lights", player) + + def _blasphemous_taranto(self, player): + return self.has("Taranto to my Sister", player) + + def _blasphemous_tirana(self, player): + return self.has("Tirana of the Celestial Bastion", player) + + def _blasphemous_aubade(self, player): + return self.has("Aubade of the Nameless Guardian", player) + + def _blasphemous_cherub_6(self, player): + return self.has_any({"Debla of the Lights", "Taranto to my Sister", "Verdiales of the Forsaken Hamlet", \ + "Tirana of the Celestial Bastion", "Cloistered Ruby"}, player) + + def _blasphemous_cherub_13(self, player): + return self.has_any({"Ranged Skill", "Debla of the Lights", "Taranto to my Sister", \ + "Cante Jondo of the Three Sisters", "Aubade of the Nameless Guardian", "Tirana of the Celestial Bastion", \ + "Cloistered Ruby"}, player) + + def _blasphemous_cherub_20(self, player): + return self.has_any({"Debla of the Lights", "Lorqiana", "Zarabanda of the Safe Haven", "Taranto to my Sister", \ + "Cante Jondo of the Three Sisters", "Aubade of the Nameless Guardian", "Tirana of the Celestial Bastion", \ + "Cloistered Ruby"}, player) + + def _blasphemous_cherub_21(self, player): + return self.has_any({"Debla of the Lights", "Taranto to my Sister", "Cante Jondo of the Three Sisters", \ + "Verdiales of the Forsaken Hamlet", "Tirana of the Celestial Bastion", "Cloistered Ruby"}, player) + + def _blasphemous_cherub_22_23_31_32(self, player): + return self.has_any({"Debla of the Lights", "Taranto to my Sister", "Cloistered Ruby"}, player) + + def _blasphemous_cherub_24_33(self, player): + return self.has_any({"Debla of the Lights", "Taranto to my Sister", "Cante Jondo of the Three Sisters", \ + "Tirana of the Celestial Bastion", "Cloistered Ruby"}, player) + + def _blasphemous_cherub_25(self, player): + return self.has_any({"Debla of the Lights", "Lorquiana", "Taranto to my Sister", \ + "Cante Jondo of the Three Sisters", "Verdiales of the Forsaken Hamlet", "Aubade of the Nameless Guardian", \ + "Cantina of the Blue Rose", "Cloistered Ruby"}, player) + + def _blasphemous_cherub_27(self, player): + return self.has_any({"Ranged Skill", "Debla of the Lights", "Lorquiana", "Taranto to my Sister", \ + "Cante Jondo of the Three Sisters", "Aubade of the Nameless Guardian", "Cantina of the Blue Rose", \ + "Cloistered Ruby"}, player) + + def _blasphemous_cherub_38(self, player): + return self.has_any({"Ranged Skill", "Lorquiana", "Cante Jondo of the Three Sisters", \ + "Aubade of the Nameless Guardian", "Cantina of the Blue Rose", "Cloistered Ruby"}, player) or \ + (self.has("The Young Mason's Wheel", player) and \ + self.has("Brilliant Heart of Dawn", player)) + + def _blasphemous_wheel(self, player): + return self.has("The Young Mason's Wheel", player) + + def _blasphemous_dawn_heart(self, player): + return self.has("Brilliant Heart of Dawn", player) + + def _blasphemous_tirso_1(self, player): + return self.has_group("tirso", player, 1) + + def _blasphemous_tirso_2(self, player): + return self.has_group("tirso", player, 2) + + def _blasphemous_tirso_3(self, player): + return self.has_group("tirso", player, 3) + + def _blasphemous_tirso_4(self, player): + return self.has_group("tirso", player, 4) + + def _blasphemous_tirso_5(self, player): + return self.has_group("tirso", player, 5) + + def _blasphemous_tirso_6(self, player): + return self.has_group("tirso", player, 6) + + def _blasphemous_tentudia_1(self, player): + return self.has_group("tentudia", player, 1) + + def _blasphemous_tentudia_2(self, player): + return self.has_group("tentudia", player, 2) + + def _blasphemous_tentudia_3(self, player): + return self.has_group("tentudia", player, 3) + + def _blasphemous_altasgracias_3(self, player): + return self.has_group("egg", player, 3) + + def _blasphemous_cherubs_20(self, player): + return self.has("Child of Moonlight", player, 20) + + def _blasphemous_cherubs_all(self, player): + return self.has("Child of Moonlight", player, 38) + + def _blasphemous_bones_4(self, player): + return self.has_group("bones", player, 4) + + def _blasphemous_bones_8(self, player): + return self.has_group("bones", player, 8) + + def _blasphemous_bones_12(self, player): + return self.has_group("bones", player, 12) + + def _blasphemous_bones_16(self, player): + return self.has_group("bones", player, 16) + + def _blasphemous_bones_20(self, player): + return self.has_group("bones", player, 20) + + def _blasphemous_bones_24(self, player): + return self.has_group("bones", player, 24) + + def _blasphemous_bones_28(self, player): + return self.has_group("bones", player, 28) + + def _blasphemous_bones_30(self, player): + return self.has_group("bones", player, 30) + + def _blasphemous_bones_32(self, player): + return self.has_group("bones", player, 32) + + def _blasphemous_bones_36(self, player): + return self.has_group("bones", player, 36) + + def _blasphemous_bones_40(self, player): + return self.has_group("bones", player, 40) + + def _blasphemous_bones_44(self, player): + return self.has_group("bones", player, 44) + + def _blasphemous_sword_1(self, player): + return self.has("Mea Culpa Upgrade", player) + + def _blasphemous_sword_2(self, player): + return self.has("Mea Culpa Upgrade", player, 2) + + def _blasphemous_sword_3(self, player): + return self.has("Mea Culpa Upgrade", player, 3) + + def _blasphemous_sword_4(self, player): + return self.has("Mea Culpa Upgrade", player, 4) + + def _blasphemous_sword_5(self, player): + return self.has("Mea Culpa Upgrade", player, 5) + + def _blasphemous_sword_6(self, player): + return self.has("Mea Culpa Upgrade", player, 6) + + def _blasphemous_sword_7(self, player): + return self.has("Mea Culpa Upgrade", player, 7) + + def _blasphemous_ranged(self, player): + return self.has("Ranged Skill", player) + + def _blasphemous_bridge_access(self, player): + return self.has_group("wounds", player, 3) + + def _blasphemous_ex_bridge_access(self, player): + return self.has_group("wounds", player, 3) or \ + (self.has("Brilliant Heart of Dawn", player) and \ + self.has("Ranged Skill", player) and \ + self.has("Blood Perpetuated in Sand", player)) or \ + (self.has("Blood Perpetuated in Sand", player) and \ + self.has("Tirana of the Celestial Bastion", player) and \ + self.has("Fervour Upgrade", player, 2)) + + def _blasphemous_1_mask(self, player): + return self.has_group("masks", player, 1) + + def _blasphemous_2_masks(self, player): + return self.has_group("masks", player, 2) + + def _blasphemous_3_masks(self, player): + return self.has_group("masks", player, 3) + + def _blasphemous_laudes_gate(self, player): + return self.has_all({"Petrified Bell", "Blood Perpetuated in Sand", "Three Gnarled Tongues", "Key of the Secular", "Key of the Scribe", "Verses Spun from Gold"}, player) + + # Ten Piedad, Tres Angustias, Our Lady of the Charred Visage + def _blasphemous_wound_boss_easy(self, player): + return self.has("Mea Culpa Upgrade", player, 2) and \ + self.has_group("power", player, 3) + + def _blasphemous_wound_boss_normal(self, player): + return self.has("Mea Culpa Upgrade", player, 1) + + def _blasphemous_wound_boss_hard(self, player): + return True + + # Esdras + def _blasphemous_esdras_boss_easy(self, player): + return self.has("Mea Culpa Upgrade", player, 3) and \ + self.has_group("power", player, 5) + + def _blasphemous_esdras_boss_normal(self, player): + return self.has("Mea Culpa Upgrade", player, 2) and \ + self.has_group("power", player, 2) + + def _blasphemous_esdras_boss_hard(self, player): + return self.has("Mea Culpa Upgrade", player, 1) and \ + self.has_group("power", player, 1) + + # Melquiades, Exposito, Quirce + def _blasphemous_mask_boss_easy(self, player): + return self.has("Mea Culpa Upgrade", player, 4) and \ + self.has_group("power", player, 8) + + def _blasphemous_mask_boss_normal(self, player): + return self.has("Mea Culpa Upgrade", player, 3) and \ + self.has_group("power", player, 4) + + def _blasphemous_mask_boss_hard(self, player): + return self.has("Mea Culpa Upgrade", player, 2) and \ + self.has_group("power", player, 2) + + # Crisanta, Isidora, Sierpes, Amanecidas, Laudes + def _blasphemous_endgame_boss_easy(self, player): + return self.has("Mea Culpa Upgrade", player, 6) and \ + self.has_group("power", player, 16) + + def _blasphemous_endgame_boss_normal(self, player): + return self.has("Mea Culpa Upgrade", player, 5) and \ + self.has_group("power", player, 8) + + def _blasphemous_endgame_boss_hard(self, player): + return self.has("Mea Culpa Upgrade", player, 4) and \ + self.has_group("power", player, 5) + + +def rules(blasphemousworld): + world = blasphemousworld.multiworld + player = blasphemousworld.player + + # entrances + for i in world.get_region("Deambulatory of His Holiness", player).entrances: + set_rule(i, lambda state: state._blasphemous_3_masks(player)) + for i in world.get_region("Ferrous Tree", player).entrances: + set_rule(i, lambda state: state._blasphemous_bridge_access(player)) + for i in world.get_region("Mother of Mothers", player).entrances: + set_rule(i, lambda state: state._blasphemous_bridge_access(player)) + for i in world.get_region("Mourning and Havoc", player).entrances: + set_rule(i, lambda state: state._blasphemous_blood_relic(player) or \ + state.can_reach(world.get_region("Mother of Mothers", player), player)) + for i in world.get_region("Patio of the Silent Steps", player).entrances: + set_rule(i, lambda state: state._blasphemous_bridge_access(player)) + for i in world.get_region("The Resting Place of the Sister", player).entrances: + set_rule(i, lambda state: state._blasphemous_blood_relic(player)) + for i in world.get_region("The Sleeping Canvases", player).entrances: + set_rule(i, lambda state: state._blasphemous_bridge_access(player)) + for i in world.get_region("Wall of the Holy Prohibitions", player).entrances: + set_rule(i, lambda state: state._blasphemous_1_mask(player) and \ + state._blasphemous_bridge_access(player)) + + # Albero + set_rule(world.get_location("Albero: Bless Linen Cloth", player), + lambda state: state._blasphemous_cloth(player)) + set_rule(world.get_location("Albero: Bless Hatched Egg", player), + lambda state: state._blasphemous_egg(player)) + set_rule(world.get_location("Albero: Bless Severed Hand", player), + lambda state: state._blasphemous_hand(player)) + set_rule(world.get_location("Albero: First gift for Cleofas", player), + lambda state: state.can_reach(world.get_region("Mother of Mothers", player))) + set_rule(world.get_location("Albero: Final gift for Cleofas", player), + lambda state: state.can_reach(world.get_region("Mother of Mothers", player)) and \ + state._blasphemous_marks(player) and \ + state._blasphemous_cord(player)) + set_rule(world.get_location("Albero: Tirso's 1st reward", player), + lambda state: state._blasphemous_tirso_1(player)) + set_rule(world.get_location("Albero: Tirso's 2nd reward", player), + lambda state: state._blasphemous_tirso_2(player)) + set_rule(world.get_location("Albero: Tirso's 3rd reward", player), + lambda state: state._blasphemous_tirso_3(player)) + set_rule(world.get_location("Albero: Tirso's 4th reward", player), + lambda state: state._blasphemous_tirso_4(player)) + set_rule(world.get_location("Albero: Tirso's 5th reward", player), + lambda state: state._blasphemous_tirso_5(player)) + set_rule(world.get_location("Albero: Tirso's 6th reward", player), + lambda state: state._blasphemous_tirso_6(player)) + set_rule(world.get_location("Albero: Tirso's final reward", player), + lambda state: state._blasphemous_tirso_6(player) and \ + state.can_reach(world.get_region("Wall of the Holy Prohibitions", player)) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player)) + set_rule(world.get_location("Albero: Lvdovico's 1st reward", player), + lambda state: state._blasphemous_tentudia_1(player)) + set_rule(world.get_location("Albero: Lvdovico's 2nd reward", player), + lambda state: state._blasphemous_tentudia_2(player)) + set_rule(world.get_location("Albero: Lvdovico's 3rd reward", player), + lambda state: state._blasphemous_tentudia_3(player)) + set_rule(world.get_location("Ossuary: Isidora, Voice of the Dead", player), + lambda state: state._blasphemous_bones_30(player)) + set_rule(world.get_location("Ossuary: 1st reward", player), + lambda state: state._blasphemous_bones_4(player)) + set_rule(world.get_location("Ossuary: 2nd reward", player), + lambda state: state._blasphemous_bones_8(player)) + set_rule(world.get_location("Ossuary: 3rd reward", player), + lambda state: state._blasphemous_bones_12(player)) + set_rule(world.get_location("Ossuary: 4th reward", player), + lambda state: state._blasphemous_bones_16(player)) + set_rule(world.get_location("Ossuary: 5th reward", player), + lambda state: state._blasphemous_bones_20(player)) + set_rule(world.get_location("Ossuary: 6th reward", player), + lambda state: state._blasphemous_bones_24(player)) + set_rule(world.get_location("Ossuary: 7th reward", player), + lambda state: state._blasphemous_bones_28(player)) + set_rule(world.get_location("Ossuary: 8th reward", player), + lambda state: state._blasphemous_bones_32(player)) + set_rule(world.get_location("Ossuary: 9th reward", player), + lambda state: state._blasphemous_bones_36(player)) + set_rule(world.get_location("Ossuary: 10th reward", player), + lambda state: state._blasphemous_bones_40(player)) + set_rule(world.get_location("Ossuary: 11th reward", player), + lambda state: state._blasphemous_bones_44(player)) + + # All the Tears of the Sea + set_rule(world.get_location("AtTotS: Miriam's gift", player), + lambda state: state._blasphemous_2_masks(player) and \ + state._blasphemous_fall_relic(player) and \ + state._blasphemous_blood_relic(player) and \ + state._blasphemous_root_relic(player) and \ + state._blasphemous_miasma_relic(player)) + + # Archcathedral Rooftops + set_rule(world.get_location("AR: Second soldier fight", player), + lambda state: state._blasphemous_1_mask(player)) + set_rule(world.get_location("AR: Third soldier fight", player), + lambda state: state._blasphemous_2_masks(player)) + set_rule(world.get_location("AR: Upper west shaft Child of Moonlight", player), + lambda state: state._blasphemous_1_mask(player)) + set_rule(world.get_location("AR: Upper west shaft chest", player), + lambda state: state._blasphemous_2_masks(player) and \ + state._blasphemous_fall_relic(player) and \ + state._blasphemous_root_relic(player)) + set_rule(world.get_location("AR: Lady of the Six Sorrows", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_miasma_relic(player) and \ + state._blasphemous_root_relic(player)) + set_rule(world.get_location("AR: Upper east shaft ledge", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_miasma_relic(player) and \ + state._blasphemous_root_relic(player) and \ + state._blasphemous_1_mask(player)) + set_rule(world.get_location("AR: Mea Culpa altar", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_miasma_relic(player) and \ + state._blasphemous_2_masks(player)) + set_rule(world.get_location("AR: Crisanta of the Wrapped Agony", player), + lambda state: state._blasphemous_3_masks(player)) + + # Bridge of the Three Cavalries + set_rule(world.get_location("BotTC: Esdras, of the Anointed Legion", player), + lambda state: state._blasphemous_bridge_access(player)) + set_rule(world.get_location("BotTC: Esdras' gift", player), + lambda state: state._blasphemous_bridge_access(player)) + set_rule(world.get_location("BotTC: Inside giant statue", player), + lambda state: state._blasphemous_bridge_access(player) and \ + state._blasphemous_laudes_gate(player) and \ + state._blasphemous_1_mask(player)) + + # Brotherhood of the Silent Sorrow + set_rule(world.get_location("BotSS: Starting room Child of Moonlight", player), + lambda state: (state._blasphemous_blood_relic(player) and \ + (state._blasphemous_root_relic(player)) or \ + (state._blasphemous_fall_relic(player))) or \ + (state._blasphemous_blood_relic(player) and \ + state._blasphemous_cherub_6(player)) or \ + (state._blasphemous_debla(player) or \ + state._blasphemous_taranto(player))) + set_rule(world.get_location("BotSS: Starting room ledge", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_fall_relic(player)) + set_rule(world.get_location("BotSS: Chamber of the Eldest Brother", player), + lambda state: state._blasphemous_elder_key(player)) + set_rule(world.get_location("BotSS: Blue candle", player), + lambda state: state._blasphemous_blue_wax(player)) + set_rule(world.get_location("BotSS: Outside church", player), + lambda state: state._blasphemous_blood_relic(player)) + set_rule(world.get_location("BotSS: Esdras' final gift", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_scapular(player) and \ + state._blasphemous_bridge_access(player)) + set_rule(world.get_location("BotSS: Crisanta's gift", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_scapular(player) and \ + state._blasphemous_heart_c(player) and \ + state._blasphemous_3_masks(player) and \ + state._blasphemous_bridge_access(player)) + + # Convent of our Lady of the Charred Visage + set_rule(world.get_location("CoOLotCV: Lower west statue", player), + lambda state: state._blasphemous_miasma_relic(player)) + set_rule(world.get_location("CoOLotCV: Lady of the Six Sorrows", player), + lambda state: state._blasphemous_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_high_key(player)) + set_rule(world.get_location("CoOLotCV: Red candle", player), + lambda state: state._blasphemous_red_wax(player)) + set_rule(world.get_location("CoOLotCV: Fountain of burning oil", player), + lambda state: state._blasphemous_thimble(player)) + set_rule(world.get_location("CoOLotCV: Mask room", player), + lambda state: state._blasphemous_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_high_key(player)) + + # Desecrated Cistern + set_rule(world.get_location("DC: Upper east tunnel chest", player), + lambda state: state._blasphemous_water_relic(player) or \ + state._blasphemous_fall_relic(player)) + set_rule(world.get_location("DC: Upper east Child of Moonlight", player), + lambda state: state._blasphemous_water_relic(player) or \ + state._blasphemous_fall_relic(player) or \ + state._blasphemous_cherub_13(player)) + set_rule(world.get_location("DC: Hidden alcove near fountain", player), + lambda state: state._blasphemous_water_relic(player)) + set_rule(world.get_location("DC: Shroud puzzle", player), + lambda state: state._blasphemous_corpse_relic(player) and \ + state._blasphemous_miasma_relic(player) and \ + state._blasphemous_water_relic(player)) + set_rule(world.get_location("DC: Chalice room", player), + lambda state: (state._blasphemous_miasma_relic(player) and \ + state._blasphemous_water_relic(player) and \ + state._blasphemous_root_relic(player)) or \ + (state._blasphemous_fall_relic(player) and \ + state._blasphemous_root_relic(player))) + set_rule(world.get_location("DC: Mea Culpa altar", player), + lambda state: state._blasphemous_chalice(player) and \ + state._blasphemous_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_miasma_relic(player) and \ + state._blasphemous_water_relic(player) and \ + state._blasphemous_root_relic(player)) + set_rule(world.get_location("DC: Child of Moonlight, behind pillar", player), + lambda state: state._blasphemous_miasma_relic(player) and \ + state._blasphemous_water_relic(player)) + set_rule(world.get_location("DC: High ledge near elevator shaft", player), + lambda state: state._blasphemous_miasma_relic(player) and \ + state._blasphemous_water_relic(player)) + set_rule(world.get_location("DC: Elevator shaft Child of Moonlight", player), + lambda state: state._blasphemous_fall_relic(player) or \ + (state._blasphemous_miasma_relic(player) and \ + state._blasphemous_water_relic(player) and \ + state._blasphemous_cherub_22_23_31_32(player))) + set_rule(world.get_location("DC: Elevator shaft ledge", player), + lambda state: state._blasphemous_fall_relic(player)) + + # Graveyard of the Peaks + set_rule(world.get_location("GotP: Shop cave Child of Moonlight", player), + lambda state: state._blasphemous_blood_relic(player) or \ + state._blasphemous_fall_relic(player) or \ + state._blasphemous_cherub_22_23_31_32(player)) + # to do: or dive + set_rule(world.get_location("GotP: Shop cave hidden hole", player), + lambda state: state._blasphemous_blood_relic(player) or \ + state._blasphemous_open_holes(player)) + set_rule(world.get_location("GotP: Upper east shaft", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_root_relic(player)) + set_rule(world.get_location("GotP: East cliffside", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_root_relic(player)) + set_rule(world.get_location("GotP: West shaft Child of Moonlight", player), + lambda state: state._blasphemous_blood_relic(player) or \ + state._blasphemous_cherub_25(player)) + set_rule(world.get_location("GotP: Center shaft Child of Moonlight", player), + lambda state: state._blasphemous_fall_relic(player) or \ + state._blasphemous_cherub_24_33(player)) + # to do: requires dive + set_rule(world.get_location("GotP: Amanecida of the Bejeweled Arrow", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_blood_relic(player) and \ + state._blasphemous_root_relic(player) and \ + state._blasphemous_open_holes(player)) + + # Grievance Ascends + set_rule(world.get_location("GA: Lower west ledge", player), + lambda state: state._blasphemous_miasma_relic(player)) + set_rule(world.get_location("GA: Miasma room floor", player), + lambda state: state._blasphemous_miasma_relic(player)) + set_rule(world.get_location("GA: Oil of the Pilgrims", player), + lambda state: state._blasphemous_blood_relic(player)) + set_rule(world.get_location("GA: End of blood bridge", player), + lambda state: state._blasphemous_blood_relic(player)) + set_rule(world.get_location("GA: Blood bridge Child of Moonlight", player), + lambda state: state._blasphemous_blood_relic(player) and \ + ((state._blasphemous_aubade(player) and \ + state._blasphemous_ranged(player)) or \ + state._blasphemous_cherub_21(player))) + set_rule(world.get_location("GA: Lower east Child of Moonlight", player), + lambda state: state._blasphemous_root_relic(player) or \ + state._blasphemous_cherub_20(player)) + set_rule(world.get_location("GA: Altasgracias' gift", player), + lambda state: state._blasphemous_altasgracias_3(player)) + set_rule(world.get_location("GA: Empty giant egg", player), + lambda state: state._blasphemous_altasgracias_3(player) and \ + state._blasphemous_egg(player)) + + # Hall of the Dawning + set_rule(world.get_location("HotD: Laudes, the First of the Amanecidas", player), + lambda state: state._blasphemous_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_laudes_gate(player)) + + # Jondo + set_rule(world.get_location("Jondo: Upper east chest", player), + lambda state: state._blasphemous_fall_relic(player) or \ + state._blasphemous_root_relic(player)) + set_rule(world.get_location("Jondo: Upper west tree root", player), + lambda state: state._blasphemous_root_relic(player) or \ + state._blasphemous_dawn_heart(player)) + + # Knot of the Three Words + set_rule(world.get_location("KotTW: Gift from the Traitor", player), + lambda state: state._blasphemous_wood_key(player) and \ + state._blasphemous_eyes(player)) + + # Library of the Negated Words + set_rule(world.get_location("LotNW: Root ceiling platform", player), + lambda state: state._blasphemous_root_relic(player)) + # to do: requires dive (sometimes opens with other skills?) + set_rule(world.get_location("LotNW: Hidden floor", player), + lambda state: state._blasphemous_open_holes(player)) + set_rule(world.get_location("LotNW: Miasma hallway chest", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_root_relic(player) and \ + state._blasphemous_miasma_relic(player)) + set_rule(world.get_location("LotNW: Platform puzzle chest", player), + lambda state: state._blasphemous_blood_relic(player)) + set_rule(world.get_location("LotNW: Elevator Child of Moonlight", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_root_relic(player)) + set_rule(world.get_location("LotNW: Red candle", player), + lambda state: state._blasphemous_red_wax(player)) + set_rule(world.get_location("LotNW: Twisted wood hidden wall", player), + lambda state: state._blasphemous_wood_key(player)) + + # Mercy Dreams + set_rule(world.get_location("MD: Blue candle", player), + lambda state: state._blasphemous_bridge_access(player) and \ + state._blasphemous_blue_wax(player)) + set_rule(world.get_location("MD: Cave Child of Moonlight", player), + lambda state: state._blasphemous_bridge_access(player) and \ + state._blasphemous_cherub_24_33(player)) + set_rule(world.get_location("MD: Behind gate to TSC", player), + lambda state: state._blasphemous_bridge_access(player)) + + # Mother of Mothers + set_rule(world.get_location("MoM: East chandelier platform", player), + lambda state: state._blasphemous_blood_relic(player) or \ + state._blasphemous_dawn_heart(player)) + set_rule(world.get_location("MoM: Redento's treasure", player), + lambda state: state._blasphemous_redento(player)) + set_rule(world.get_location("MoM: Final meeting with Redento", player), + lambda state: state._blasphemous_redento(player)) + set_rule(world.get_location("MoM: Giant chandelier statue", player), + lambda state: state._blasphemous_blood_relic(player)) + + # Mountains of the Endless Dusk + set_rule(world.get_location("MotED: Platform above chasm", player), + lambda state: state._blasphemous_blood_relic(player)) + set_rule(world.get_location("MotED: Blood platform alcove", player), + lambda state: state._blasphemous_blood_relic(player)) + set_rule(world.get_location("MotED: Egg hatching", player), + lambda state: state._blasphemous_pre_egg(player)) + # to do: requires dive + set_rule(world.get_location("MotED: Amanecida of the Golden Blades", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_open_holes(player)) + + # Mourning and Havoc + set_rule(world.get_location("MaH: Upper east chest", player), + lambda state: state._blasphemous_bridge_access(player) and \ + state._blasphemous_root_relic(player)) + set_rule(world.get_location("MaH: Sierpes' eye", player), + lambda state: state._blasphemous_bridge_access(player) and \ + (state._blasphemous_root_relic(player)) or \ + state._blasphemous_water_relic(player) or \ + state._blasphemous_dawn_heart(player)) + set_rule(world.get_location("MaH: Sierpes", player), + lambda state: state._blasphemous_bridge_access(player) and \ + (state._blasphemous_root_relic(player)) or \ + state._blasphemous_water_relic(player) or \ + state._blasphemous_dawn_heart(player)) + + # Patio of the Silent Steps + set_rule(world.get_location("PotSS: Second area ledge", player), + lambda state: state._blasphemous_root_relic(player) or \ + state._blasphemous_dawn_heart(player) or \ + (state._blasphemous_wheel(player) and \ + state._blasphemous_ranged(player))) + set_rule(world.get_location("PotSS: Third area upper ledge", player), + lambda state: state._blasphemous_root_relic(player) or \ + state._blasphemous_dawn_heart(player)) + set_rule(world.get_location("PotSS: Climb to WotHP", player), + lambda state: (state._blasphemous_blood_relic(player) and \ + state._blasphemous_root_relic(player)) or \ + (state.can_reach(world.get_region("Wall of the Holy Prohibitions", player)) and \ + state._blasphemous_bronze_key(player))) + # to do: requires dive + set_rule(world.get_location("PotSS: Amanecida of the Chiselled Steel", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_open_holes(player)) + + # Petrous + # to do: requires dive + set_rule(world.get_location("Petrous: Temple entrance", player), + lambda state: state._blasphemous_open_holes(player)) + + # The Sleeping Canvases + set_rule(world.get_location("TSC: Candle wax puzzle", player), + lambda state: state._blasphemous_both_wax(player)) + set_rule(world.get_location("TSC: Under elevator shaft", player), + lambda state: state._blasphemous_fall_relic(player)) + set_rule(world.get_location("TSC: Jocinero's 1st reward", player), + lambda state: state._blasphemous_cherubs_20(player)) + set_rule(world.get_location("TSC: Jocinero's final reward", player), + lambda state: state._blasphemous_cherubs_all(player)) + + # The Holy Line + set_rule(world.get_location("THL: Across blood platforms", player), + lambda state: state._blasphemous_blood_relic(player)) + set_rule(world.get_location("THL: Underground chest", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_water_relic(player)) + + # Wall of the Holy Prohibitions + set_rule(world.get_location("WotHP: Upper east room, top bronze cell", player), + lambda state: state._blasphemous_bronze_key(player)) + set_rule(world.get_location("WotHP: Upper east room, top silver cell", player), + lambda state: state._blasphemous_silver_key(player)) + set_rule(world.get_location("WotHP: Upper east room, center gold cell", player), + lambda state: state._blasphemous_gold_key(player)) + set_rule(world.get_location("WotHP: Upper west room, center gold cell", player), + lambda state: state._blasphemous_gold_key(player) and \ + state._blasphemous_bronze_key(player)) + set_rule(world.get_location("WotHP: Lower west room, bottom gold cell", player), + lambda state: state._blasphemous_gold_key(player) and \ + state._blasphemous_bronze_key(player)) + set_rule(world.get_location("WotHP: Upper west room, top silver cell", player), + lambda state: state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player)) + set_rule(world.get_location("WotHP: Lower west room, top ledge", player), + lambda state: state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player)) + set_rule(world.get_location("WotHP: Lower east room, hidden ledge", player), + lambda state: state._blasphemous_bronze_key(player)) + set_rule(world.get_location("WotHP: Lower east room, bottom silver cell", player), + lambda state: state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player)) + set_rule(world.get_location("WotHP: Lower east room, top bronze cell", player), + lambda state: state._blasphemous_bronze_key(player)) + set_rule(world.get_location("WotHP: Lower east room, top silver cell", player), + lambda state: state._blasphemous_silver_key(player)) + set_rule(world.get_location("WotHP: Outside Child of Moonlight", player), + lambda state: state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player)) + set_rule(world.get_location("WotHP: Oil of the Pilgrims", player), + lambda state: state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player)) + set_rule(world.get_location("WotHP: Quirce, Returned By The Flames", player), + lambda state: state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player)) + set_rule(world.get_location("WotHP: Collapsing floor ledge", player), + lambda state: state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player)) + set_rule(world.get_location("WotHP: Amanecida of the Molten Thorn", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player)) + + # Wasteland of the Buried Churches + set_rule(world.get_location("WotBC: Under broken bridge", player), + lambda state: state._blasphemous_blood_relic(player) or \ + state._blasphemous_dawn_heart(player)) + set_rule(world.get_location("WotBC: Cliffside Child of Moonlight", player), + lambda state: state._blasphemous_cherub_38(player)) + + # Where Olive Trees Wither + set_rule(world.get_location("WOTW: Gift for the tomb", player), + lambda state: state._blasphemous_full_thimble(player)) + set_rule(world.get_location("WOTW: Underground tomb", player), + lambda state: state._blasphemous_flowers(player) and \ + (state._blasphemous_full_thimble(player) or \ + state._blasphemous_fall_relic(player))) + set_rule(world.get_location("WOTW: Underground Child of Moonlight", player), + lambda state: (state._blasphemous_full_thimble(player) or \ + state._blasphemous_fall_relic(player)) and \ + state._blasphemous_cherub_27(player)) + set_rule(world.get_location("WOTW: Underground ledge", player), + lambda state: (state._blasphemous_full_thimble(player) or \ + state._blasphemous_fall_relic(player)) and \ + state._blasphemous_blood_relic(player)) + set_rule(world.get_location("WOTW: Upper east Child of Moonlight", player), + lambda state: state._blasphemous_root_relic(player) or \ + state._blasphemous_cherub_22_23_31_32(player)) + set_rule(world.get_location("WOTW: Upper east statue", player), + lambda state: state._blasphemous_root_relic(player)) + set_rule(world.get_location("WOTW: Gemino's reward", player), + lambda state: state._blasphemous_full_thimble(player)) + + # Various + set_rule(world.get_location("Confessor Dungeon 1 extra", player), + lambda state: state._blasphemous_bead(player)) + set_rule(world.get_location("Confessor Dungeon 1 main", player), + lambda state: state._blasphemous_bead(player)) + set_rule(world.get_location("Confessor Dungeon 2 extra", player), + lambda state: state._blasphemous_bead(player)) + set_rule(world.get_location("Confessor Dungeon 2 main", player), + lambda state: state._blasphemous_bead(player)) + set_rule(world.get_location("Confessor Dungeon 3 extra", player), + lambda state: state._blasphemous_bead(player)) + set_rule(world.get_location("Confessor Dungeon 3 main", player), + lambda state: state._blasphemous_bead(player)) + set_rule(world.get_location("Confessor Dungeon 4 extra", player), + lambda state: state._blasphemous_bead(player)) + set_rule(world.get_location("Confessor Dungeon 4 main", player), + lambda state: state._blasphemous_bead(player)) + set_rule(world.get_location("Confessor Dungeon 5 extra", player), + lambda state: state._blasphemous_bead(player) and \ + state._blasphemous_bridge_access(player)) + set_rule(world.get_location("Confessor Dungeon 5 main", player), + lambda state: state._blasphemous_bead(player) and \ + state._blasphemous_bridge_access(player)) + set_rule(world.get_location("Confessor Dungeon 6 extra", player), + lambda state: state._blasphemous_bead(player) and \ + state._blasphemous_bridge_access(player) and \ + (state._blasphemous_1_mask(player) or \ + state._blasphemous_blood_relic(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player))) + set_rule(world.get_location("Confessor Dungeon 6 main", player), + lambda state: state._blasphemous_bead(player) and \ + state._blasphemous_bridge_access(player) and \ + (state._blasphemous_1_mask(player) or \ + state._blasphemous_blood_relic(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player))) + set_rule(world.get_location("Confessor Dungeon 7 extra", player), + lambda state: state._blasphemous_bead(player) and \ + state._blasphemous_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_blood_relic(player)) + set_rule(world.get_location("Confessor Dungeon 7 main", player), + lambda state: state._blasphemous_bead(player) and \ + state._blasphemous_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_blood_relic(player)) + # to do: requires dive + set_rule(world.get_location("Defeat 1 Amanecida", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_open_holes(player)) + set_rule(world.get_location("Defeat 2 Amanecidas", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_open_holes(player) and \ + state._blasphemous_blood_relic(player) and \ + (state._blasphemous_root_relic(player) or \ + state._blasphemous_bridge_access(player))) + set_rule(world.get_location("Defeat 3 Amanecidas", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_open_holes(player) and \ + state._blasphemous_bridge_access(player) and \ + state._blasphemous_blood_relic(player) and \ + (state._blasphemous_root_relic(player) or \ + (state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player)))) + set_rule(world.get_location("Defeat 4 Amanecidas", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_open_holes(player) and \ + state._blasphemous_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_blood_relic(player) and \ + state._blasphemous_root_relic(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player)) + set_rule(world.get_location("Defeat all Amanecidas", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_open_holes(player) and \ + state._blasphemous_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_blood_relic(player) and \ + state._blasphemous_root_relic(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player)) + + # expert logic + if world.expert_logic[player]: + # entrances + for i in world.get_region("Ferrous Tree", player).entrances: + set_rule(i, lambda state: state._blasphemous_ex_bridge_access(player)) + for i in world.get_region("Mother of Mothers", player).entrances: + set_rule(i, lambda state: state._blasphemous_ex_bridge_access(player)) + for i in world.get_region("Patio of the Silent Steps", player).entrances: + set_rule(i, lambda state: state._blasphemous_ex_bridge_access(player)) + for i in world.get_region("The Sleeping Canvases", player).entrances: + set_rule(i, lambda state: state._blasphemous_ex_bridge_access(player)) + for i in world.get_region("Wall of the Holy Prohibitions", player).entrances: + set_rule(i, lambda state: state._blasphemous_1_mask(player) and \ + state._blasphemous_ex_bridge_access(player)) + + # locations + set_rule(world.get_location("AR: Upper west shaft chest", player), + lambda state: state._blasphemous_2_masks(player) and \ + state._blasphemous_fall_relic(player) and \ + (state._blasphemous_root_relic(player) or \ + state._blasphemous_ranged(player))) + set_rule(world.get_location("BotTC: Esdras, of the Anointed Legion", player), + lambda state: state._blasphemous_ex_bridge_access(player)) + set_rule(world.get_location("BotTC: Esdras' gift", player), + lambda state: state._blasphemous_ex_bridge_access(player)) + set_rule(world.get_location("BotTC: Inside giant statue", player), + lambda state: state._blasphemous_ex_bridge_access(player) and \ + state._blasphemous_laudes_gate(player) and \ + state._blasphemous_1_mask(player)) + set_rule(world.get_location("BotSS: Esdras' final gift", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_scapular(player) and \ + state._blasphemous_ex_bridge_access(player)) + set_rule(world.get_location("BotSS: Crisanta's gift", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_scapular(player) and \ + state._blasphemous_heart_c(player) and \ + state._blasphemous_3_masks(player) and \ + state._blasphemous_ex_bridge_access(player)) + set_rule(world.get_location("CoOLotCV: Lady of the Six Sorrows", player), + lambda state: state._blasphemous_ex_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_high_key(player)) + set_rule(world.get_location("CoOLotCV: Mask room", player), + lambda state: state._blasphemous_ex_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_high_key(player)) + set_rule(world.get_location("DC: Chalice room", player), + lambda state: (state._blasphemous_miasma_relic(player) and \ + state._blasphemous_water_relic(player) and \ + (state._blasphemous_root_relic(player) or \ + state._blasphemous_dawn_heart(player) or \ + (state._blasphemous_wheel(player) and \ + state._blasphemous_ranged(player)))) or \ + (state._blasphemous_fall_relic(player) and \ + (state._blasphemous_root_relic(player) or \ + state._blasphemous_ranged(player)))) + set_rule(world.get_location("DC: Mea Culpa altar", player), + lambda state: state._blasphemous_chalice(player) and \ + state._blasphemous_ex_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + (state._blasphemous_fall_relic(player) and \ + (state._blasphemous_ranged(player) or \ + state._blasphemous_root_relic(player))) or \ + (state._blasphemous_miasma_relic(player) and \ + state._blasphemous_water_relic(player) and \ + (state._blasphemous_root_relic(player) or \ + state._blasphemous_dawn_heart(player) or \ + (state._blasphemous_wheel(player) and \ + state._blasphemous_ranged(player))))) + set_rule(world.get_location("HotD: Laudes, the First of the Amanecidas", player), + lambda state: state._blasphemous_ex_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_laudes_gate(player)) + set_rule(world.get_location("LotNW: Elevator Child of Moonlight", player), + lambda state: state._blasphemous_blood_relic(player) and \ + (state._blasphemous_cherub_22_23_31_32(player) and \ + state._blasphemous_dawn_heart(player) and \ + state._blasphemous_ranged(player)) or \ + state._blasphemous_root_relic(player)) + set_rule(world.get_location("MD: Cave Child of Moonlight", player), + lambda state: state._blasphemous_ex_bridge_access(player) and \ + state._blasphemous_cherub_24_33(player)) + set_rule(world.get_location("MD: Behind gate to TSC", player), + lambda state: state._blasphemous_ex_bridge_access(player)) + set_rule(world.get_location("MoM: East chandelier platform", player), + lambda state: state._blasphemous_blood_relic(player) or \ + state._blasphemous_dawn_heart(player) or \ + (state._blasphemous_wheel(player) and \ + state._blasphemous_ranged(player))) + set_rule(world.get_location("MaH: Upper east chest", player), + lambda state: state._blasphemous_ex_bridge_access(player) and \ + (state._blasphemous_root_relic(player)) or \ + (state._blasphemous_dawn_heart(player) and \ + state._blasphemous_ranged(player))) + set_rule(world.get_location("MaH: Sierpes' eye", player), + lambda state: state._blasphemous_ex_bridge_access(player) and \ + (state._blasphemous_root_relic(player)) or \ + state._blasphemous_dawn_heart(player) or \ + state._blasphemous_water_relic(player) or \ + (state._blasphemous_wheel(player) and \ + state._blasphemous_ranged(player))) + set_rule(world.get_location("MaH: Sierpes", player), + lambda state: state._blasphemous_ex_bridge_access(player) and \ + (state._blasphemous_root_relic(player)) or \ + state._blasphemous_dawn_heart(player) or \ + state._blasphemous_water_relic(player) or \ + (state._blasphemous_wheel(player) and \ + state._blasphemous_ranged(player))) + set_rule(world.get_location("PotSS: Third area upper ledge", player), + lambda state: state._blasphemous_root_relic(player) or \ + state._blasphemous_dawn_heart(player) or \ + (state._blasphemous_wheel(player) and \ + state._blasphemous_ranged(player))) + set_rule(world.get_location("WotBC: Under broken bridge", player), + lambda state: state._blasphemous_blood_relic(player) or \ + state._blasphemous_dawn_heart(player) or \ + (state._blasphemous_wheel(player) and \ + state._blasphemous_ranged(player))) + set_rule(world.get_location("Confessor Dungeon 5 extra", player), + lambda state: state._blasphemous_bead(player) and \ + state._blasphemous_ex_bridge_access(player)) + set_rule(world.get_location("Confessor Dungeon 5 main", player), + lambda state: state._blasphemous_bead(player) and \ + state._blasphemous_ex_bridge_access(player)) + set_rule(world.get_location("Confessor Dungeon 6 extra", player), + lambda state: state._blasphemous_bead(player) and \ + state._blasphemous_ex_bridge_access(player) and \ + (state._blasphemous_1_mask(player) or \ + state._blasphemous_blood_relic(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player))) + set_rule(world.get_location("Confessor Dungeon 6 main", player), + lambda state: state._blasphemous_bead(player) and \ + state._blasphemous_ex_bridge_access(player) and \ + (state._blasphemous_1_mask(player) or \ + state._blasphemous_blood_relic(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_bronze_key(player))) + set_rule(world.get_location("Confessor Dungeon 7 extra", player), + lambda state: state._blasphemous_bead(player) and \ + state._blasphemous_ex_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_blood_relic(player)) + set_rule(world.get_location("Confessor Dungeon 7 main", player), + lambda state: state._blasphemous_bead(player) and \ + state._blasphemous_ex_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player) and \ + state._blasphemous_blood_relic(player)) + set_rule(world.get_location("Defeat 2 Amanecidas", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_open_holes(player) and \ + state._blasphemous_blood_relic(player) and \ + (state._blasphemous_root_relic(player) or \ + state._blasphemous_ex_bridge_access(player))) + set_rule(world.get_location("Defeat 3 Amanecidas", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_open_holes(player) and \ + state._blasphemous_ex_bridge_access(player) and \ + state._blasphemous_blood_relic(player) and \ + (state._blasphemous_root_relic(player) or \ + (state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player)))) + set_rule(world.get_location("Defeat 4 Amanecidas", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_open_holes(player) and \ + state._blasphemous_ex_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_blood_relic(player) and \ + state._blasphemous_root_relic(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player)) + set_rule(world.get_location("Defeat all Amanecidas", player), + lambda state: state._blasphemous_bell(player) and \ + state._blasphemous_open_holes(player) and \ + state._blasphemous_ex_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_blood_relic(player) and \ + state._blasphemous_root_relic(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_silver_key(player)) + + # skill rando + if world.skill_randomizer[player] and not world.expert_logic[player]: + set_rule(world.get_location("Skill 1, Tier 3", player), + lambda state: state._blasphemous_bridge_access(player)) + set_rule(world.get_location("Skill 5, Tier 3", player), + lambda state: state._blasphemous_bridge_access(player)) + set_rule(world.get_location("Skill 3, Tier 2", player), + lambda state: state._blasphemous_bridge_access(player)) + set_rule(world.get_location("Skill 2, Tier 3", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_miasma_relic(player) and \ + state._blasphemous_2_masks(player) and \ + state._blasphemous_bridge_access(player)) + set_rule(world.get_location("Skill 4, Tier 3", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_miasma_relic(player) and \ + state._blasphemous_2_masks(player) and \ + state._blasphemous_bridge_access(player)) + set_rule(world.get_location("Skill 3, Tier 3", player), + lambda state: state._blasphemous_chalice(player) and \ + state._blasphemous_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + state._blasphemous_miasma_relic(player) and \ + state._blasphemous_water_relic(player) and \ + state._blasphemous_root_relic(player)) + elif world.skill_randomizer[player] and world.expert_logic[player]: + set_rule(world.get_location("Skill 1, Tier 3", player), + lambda state: state._blasphemous_ex_bridge_access(player)) + set_rule(world.get_location("Skill 5, Tier 3", player), + lambda state: state._blasphemous_ex_bridge_access(player)) + set_rule(world.get_location("Skill 3, Tier 2", player), + lambda state: state._blasphemous_ex_bridge_access(player)) + set_rule(world.get_location("Skill 2, Tier 3", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_miasma_relic(player) and \ + state._blasphemous_2_masks(player) and \ + state._blasphemous_ex_bridge_access(player)) + set_rule(world.get_location("Skill 4, Tier 3", player), + lambda state: state._blasphemous_blood_relic(player) and \ + state._blasphemous_miasma_relic(player) and \ + state._blasphemous_2_masks(player) and \ + state._blasphemous_ex_bridge_access(player)) + set_rule(world.get_location("Skill 3, Tier 3", player), + lambda state: state._blasphemous_chalice(player) and \ + state._blasphemous_ex_bridge_access(player) and \ + state._blasphemous_1_mask(player) and \ + state._blasphemous_bronze_key(player) and \ + (state._blasphemous_fall_relic(player) and \ + (state._blasphemous_ranged(player) or \ + state._blasphemous_root_relic(player))) or \ + (state._blasphemous_miasma_relic(player) and \ + state._blasphemous_water_relic(player) and \ + (state._blasphemous_root_relic(player) or \ + state._blasphemous_dawn_heart(player) or \ + (state._blasphemous_wheel(player) and \ + state._blasphemous_ranged(player))))) + + # difficulty (easy) + if world.difficulty[player].value == 0: + for i in world.get_region("Desecrated Cistern", player).entrances: + add_rule(i, lambda state: state._blasphemous_wound_boss_easy(player)) + for i in world.get_region("Ferrous Tree", player).entrances: + add_rule(i, lambda state: state._blasphemous_esdras_boss_easy(player)) + for i in world.get_region("Patio of the Silent Steps", player).entrances: + add_rule(i, lambda state: state._blasphemous_esdras_boss_easy(player)) + for i in world.get_region("The Sleeping Canvases", player).entrances: + add_rule(i, lambda state: state._blasphemous_esdras_boss_easy(player)) + for i in world.get_region("Deambulatory of His Holiness", player).entrances: + add_rule(i, lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("Albero: Donate 5000 Tears", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("Albero: Donate 50000 Tears", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("Albero: Tirso's final reward", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("Ossuary: Isidora, Voice of the Dead", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("AR: Crisanta of the Wrapped Agony", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("BotTC: Esdras, of the Anointed Legion", player), + lambda state: state._blasphemous_esdras_boss_easy(player)) + add_rule(world.get_location("BotTC: Esdras' gift", player), + lambda state: state._blasphemous_esdras_boss_easy(player)) + add_rule(world.get_location("BotTC: Inside giant statue", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("BotSS: Crisanta's gift", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("CoOLotCV: Lady of the Six Sorrows", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("CoOLotCV: Mask room", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("GotP: Amanecida of the Bejeweled Arrow", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("HotD: Laudes, the First of the Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("LotNW: Elevator Child of Moonlight", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("LotNW: Mask room", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("LotNW: Mea Culpa altar", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("LotNW: Red candle", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("MD: Blue candle", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("MD: Cave Child of Moonlight", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("MD: Behind gate to TSC", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("MoM: Melquiades, The Exhumed Archbishop", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("MoM: Mask room", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("MotED: Amanecida of the Golden Blades", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("MaH: Sierpes' eye", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("MaH: Sierpes", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("PotSS: Amanecida of the Chiselled Steel", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("TSC: Under elevator shaft", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("TSC: Exposito, Scion of Abjuration", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("WotHP: Quirce, Returned By The Flames", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("WotHP: Collapsing floor ledge", player), + lambda state: state._blasphemous_mask_boss_easy(player)) + add_rule(world.get_location("WotHP: Amanecida of the Molten Thorn", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("Confessor Dungeon 4 extra", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("Confessor Dungeon 4 main", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("Confessor Dungeon 5 extra", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("Confessor Dungeon 5 main", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("Confessor Dungeon 6 extra", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("Confessor Dungeon 6 main", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("Confessor Dungeon 7 extra", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("Confessor Dungeon 7 main", player), + lambda state: state._blasphemous_wound_boss_easy(player)) + add_rule(world.get_location("Defeat 1 Amanecida", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("Defeat 2 Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("Defeat 3 Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("Defeat 4 Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + add_rule(world.get_location("Defeat all Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_easy(player)) + + # difficulty (normal) + elif world.difficulty[player].value == 1: + for i in world.get_region("Desecrated Cistern", player).entrances: + add_rule(i, lambda state: state._blasphemous_wound_boss_normal(player)) + for i in world.get_region("Ferrous Tree", player).entrances: + add_rule(i, lambda state: state._blasphemous_esdras_boss_normal(player)) + for i in world.get_region("Patio of the Silent Steps", player).entrances: + add_rule(i, lambda state: state._blasphemous_esdras_boss_normal(player)) + for i in world.get_region("The Sleeping Canvases", player).entrances: + add_rule(i, lambda state: state._blasphemous_esdras_boss_normal(player)) + for i in world.get_region("Deambulatory of His Holiness", player).entrances: + add_rule(i, lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("Albero: Donate 5000 Tears", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("Albero: Donate 50000 Tears", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("Albero: Tirso's final reward", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("Ossuary: Isidora, Voice of the Dead", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("AR: Crisanta of the Wrapped Agony", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("BotTC: Esdras, of the Anointed Legion", player), + lambda state: state._blasphemous_esdras_boss_normal(player)) + add_rule(world.get_location("BotTC: Esdras' gift", player), + lambda state: state._blasphemous_esdras_boss_normal(player)) + add_rule(world.get_location("BotTC: Inside giant statue", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("BotSS: Crisanta's gift", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("CoOLotCV: Lady of the Six Sorrows", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("CoOLotCV: Mask room", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("GotP: Amanecida of the Bejeweled Arrow", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("HotD: Laudes, the First of the Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("LotNW: Elevator Child of Moonlight", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("LotNW: Mask room", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("LotNW: Mea Culpa altar", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("LotNW: Red candle", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("MD: Blue candle", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("MD: Cave Child of Moonlight", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("MD: Behind gate to TSC", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("MoM: Melquiades, The Exhumed Archbishop", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("MoM: Mask room", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("MotED: Amanecida of the Golden Blades", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("MaH: Sierpes' eye", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("MaH: Sierpes", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("PotSS: Amanecida of the Chiselled Steel", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("TSC: Under elevator shaft", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("TSC: Exposito, Scion of Abjuration", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("WotHP: Quirce, Returned By The Flames", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("WotHP: Collapsing floor ledge", player), + lambda state: state._blasphemous_mask_boss_normal(player)) + add_rule(world.get_location("WotHP: Amanecida of the Molten Thorn", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("Confessor Dungeon 4 extra", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("Confessor Dungeon 4 main", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("Confessor Dungeon 5 extra", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("Confessor Dungeon 5 main", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("Confessor Dungeon 6 extra", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("Confessor Dungeon 6 main", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("Confessor Dungeon 7 extra", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("Confessor Dungeon 7 main", player), + lambda state: state._blasphemous_wound_boss_normal(player)) + add_rule(world.get_location("Defeat 1 Amanecida", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("Defeat 2 Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("Defeat 3 Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("Defeat 4 Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + add_rule(world.get_location("Defeat all Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_normal(player)) + + # difficulty (hard) + elif world.difficulty[player].value == 2: + for i in world.get_region("Desecrated Cistern", player).entrances: + add_rule(i, lambda state: state._blasphemous_wound_boss_hard(player)) + for i in world.get_region("Ferrous Tree", player).entrances: + add_rule(i, lambda state: state._blasphemous_esdras_boss_hard(player)) + for i in world.get_region("Patio of the Silent Steps", player).entrances: + add_rule(i, lambda state: state._blasphemous_esdras_boss_hard(player)) + for i in world.get_region("The Sleeping Canvases", player).entrances: + add_rule(i, lambda state: state._blasphemous_esdras_boss_hard(player)) + for i in world.get_region("Deambulatory of His Holiness", player).entrances: + add_rule(i, lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("Albero: Donate 5000 Tears", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("Albero: Donate 50000 Tears", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("Albero: Tirso's final reward", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("Ossuary: Isidora, Voice of the Dead", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("AR: Crisanta of the Wrapped Agony", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("BotTC: Esdras, of the Anointed Legion", player), + lambda state: state._blasphemous_esdras_boss_hard(player)) + add_rule(world.get_location("BotTC: Esdras' gift", player), + lambda state: state._blasphemous_esdras_boss_hard(player)) + add_rule(world.get_location("BotTC: Inside giant statue", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("BotSS: Crisanta's gift", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("CoOLotCV: Lady of the Six Sorrows", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("CoOLotCV: Mask room", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("GotP: Amanecida of the Bejeweled Arrow", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("HotD: Laudes, the First of the Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("LotNW: Elevator Child of Moonlight", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("LotNW: Mask room", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("LotNW: Mea Culpa altar", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("LotNW: Red candle", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("MD: Blue candle", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("MD: Cave Child of Moonlight", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("MD: Behind gate to TSC", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("MoM: Melquiades, The Exhumed Archbishop", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("MoM: Mask room", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("MotED: Amanecida of the Golden Blades", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("MaH: Sierpes' eye", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("MaH: Sierpes", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("PotSS: Amanecida of the Chiselled Steel", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("TSC: Under elevator shaft", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("TSC: Exposito, Scion of Abjuration", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("WotHP: Quirce, Returned By The Flames", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("WotHP: Collapsing floor ledge", player), + lambda state: state._blasphemous_mask_boss_hard(player)) + add_rule(world.get_location("WotHP: Amanecida of the Molten Thorn", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("Confessor Dungeon 4 extra", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("Confessor Dungeon 4 main", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("Confessor Dungeon 5 extra", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("Confessor Dungeon 5 main", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("Confessor Dungeon 6 extra", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("Confessor Dungeon 6 main", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("Confessor Dungeon 7 extra", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("Confessor Dungeon 7 main", player), + lambda state: state._blasphemous_wound_boss_hard(player)) + add_rule(world.get_location("Defeat 1 Amanecida", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("Defeat 2 Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("Defeat 3 Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("Defeat 4 Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) + add_rule(world.get_location("Defeat all Amanecidas", player), + lambda state: state._blasphemous_endgame_boss_hard(player)) \ No newline at end of file diff --git a/worlds/blasphemous/Vanilla.py b/worlds/blasphemous/Vanilla.py new file mode 100644 index 00000000..82ec7c5f --- /dev/null +++ b/worlds/blasphemous/Vanilla.py @@ -0,0 +1,246 @@ +from typing import Set, Dict + +unrandomized_dict: Dict[str, str] = { + "CoOLotCV: Fountain of burning oil": "Golden Thimble Filled with Burning Oil", + "MotED: Egg hatching": "Hatched Egg of Deformity", + "BotSS: Crisanta's gift": "Holy Wound of Abnegation", + "DC: Chalice room": "Chalice of Inverted Verses" +} + +cherub_set: Set[str] = [ + "Albero: Child of Moonlight", + "AR: Upper west shaft Child of Moonlight", + "BotSS: Starting room Child of Moonlight", + "DC: Child of Moonlight, above water", + "DC: Upper east Child of Moonlight", + "DC: Child of Moonlight, miasma room", + "DC: Child of Moonlight, behind pillar", + "DC: Top of elevator Child of Moonlight", + "DC: Elevator shaft Child of Moonlight", + "GotP: Shop cave Child of Moonlight", + "GotP: Elevator shaft Child of Moonlight", + "GotP: West shaft Child of Moonlight", + "GotP: Center shaft Child of Moonlight", + "GA: Miasma room Child of Moonlight", + "GA: Blood bridge Child of Moonlight", + "GA: Lower east Child of Moonlight", + "Jondo: Upper east Child of Moonlight", + "Jondo: Spike tunnel Child of Moonlight", + "Jondo: Upper west Child of Moonlight", + "LotNW: Platform room Child of Moonlight", + "LotNW: Lowest west Child of Moonlight", + "LotNW: Elevator Child of Moonlight", + "MD: Second area Child of Moonlight", + "MD: Cave Child of Moonlight", + "MoM: Lower west Child of Moonlight", + "MoM: Upper center Child of Moonlight", + "MotED: Child of Moonlight, above chasm", + "PotSS: First area Child of Moonlight", + "PotSS: Third area Child of Moonlight", + "THL: Child of Moonlight", + "WotHP: Upper east room, top bronze cell", + "WotHP: Upper west room, top silver cell", + "WotHP: Lower east room, bottom silver cell", + "WotHP: Outside Child of Moonlight", + "WotBC: Outside Child of Moonlight", + "WotBC: Cliffside Child of Moonlight", + "WOTW: Underground Child of Moonlight", + "WOTW: Upper east Child of Moonlight", +] + +life_set: Set[str] = [ + "AR: Lady of the Six Sorrows", + "CoOLotCV: Lady of the Six Sorrows", + "DC: Lady of the Six Sorrows, from MD", + "DC: Lady of the Six Sorrows, elevator shaft", + "GotP: Lady of the Six Sorrows", + "LotNW: Lady of the Six Sorrows" +] + +fervour_set: Set[str] = [ + "DC: Oil of the Pilgrims", + "GotP: Oil of the Pilgrims", + "GA: Oil of the Pilgrims", + "LotNW: Oil of the Pilgrims", + "MoM: Oil of the Pilgrims", + "WotHP: Oil of the Pilgrims" +] + +sword_set: Set[str] = [ + "Albero: Mea Culpa altar", + "AR: Mea Culpa altar", + "BotSS: Mea Culpa altar", + "CoOLotCV: Mea Culpa altar", + "DC: Mea Culpa altar", + "LotNW: Mea Culpa altar", + "MoM: Mea Culpa altar" +] + +blessing_dict: Dict[str, str] = { + "Albero: Bless Severed Hand": "Incorrupt Hand of the Fraternal Master", + "Albero: Bless Linen Cloth": "Shroud of Dreamt Sins", + "Albero: Bless Hatched Egg": "Three Gnarled Tongues" +} + +dungeon_dict: Dict[str, str] = { + "Confessor Dungeon 1 extra": "Tears of Atonement (1000)", + "Confessor Dungeon 2 extra": "Heart of the Single Tone", + "Confessor Dungeon 3 extra": "Tears of Atonement (3000)", + "Confessor Dungeon 4 extra": "Embers of a Broken Star", + "Confessor Dungeon 5 extra": "Tears of Atonement (5000)", + "Confessor Dungeon 6 extra": "Scaly Coin", + "Confessor Dungeon 7 extra": "Seashell of the Inverted Spiral" +} + +tirso_dict: Dict[str, str] = { + "Albero: Tirso's 1st reward": "Linen Cloth", + "Albero: Tirso's 2nd reward": "Tears of Atonement (500)", + "Albero: Tirso's 3rd reward": "Tears of Atonement (1000)", + "Albero: Tirso's 4th reward": "Tears of Atonement (2000)", + "Albero: Tirso's 5th reward": "Tears of Atonement (5000)", + "Albero: Tirso's 6th reward": "Tears of Atonement (10000)", + "Albero: Tirso's final reward": "Knot of Rosary Rope" +} + +redento_dict: Dict[str, str] = { + "MoM: Redento's treasure": "Nail Uprooted from Dirt", + "MoM: Final meeting with Redento": "Knot of Rosary Rope", + "MotED: 1st meeting with Redento": "Fourth Toe made of Limestone", + "PotSS: 4th meeting with Redento": "Big Toe made of Limestone", + "WotBC: 3rd meeting with Redento": "Little Toe made of Limestone" +} + +jocinero_dict: Dict[str, str] = { + "TSC: Jocinero's 1st reward": "Linen of Golden Thread", + "TSC: Jocinero's final reward": "Campanillero to the Sons of the Aurora" +} + +altasgracias_dict: Dict[str, str] = { + "GA: Altasgracias' gift": "Egg of Deformity", + "GA: Empty giant egg": "Knot of Hair" +} + +tentudia_dict: Dict[str, str] = { + "Albero: Lvdovico's 1st reward": "Tears of Atonement (500)", + "Albero: Lvdovico's 2nd reward": "Tears of Atonement (1000)", + "Albero: Lvdovico's 3rd reward": "Debla of the Lights" +} + +gemino_dict: Dict[str, str] = { + "WOTW: Gift for the tomb": "Dried Flowers bathed in Tears", + "WOTW: Underground tomb": "Saeta Dolorosa", + "WOTW: Gemino's gift": "Empty Golden Thimble", + "WOTW: Gemino's reward": "Frozen Olive" +} + +ossuary_dict: Dict[str, str] = { + "Ossuary: 1st reward": "Tears of Atonement (250)", + "Ossuary: 2nd reward": "Tears of Atonement (500)", + "Ossuary: 3rd reward": "Tears of Atonement (750)", + "Ossuary: 4th reward": "Tears of Atonement (1000)", + "Ossuary: 5th reward": "Tears of Atonement (1250)", + "Ossuary: 6th reward": "Tears of Atonement (1500)", + "Ossuary: 7th reward": "Tears of Atonement (1750)", + "Ossuary: 8th reward": "Tears of Atonement (2000)", + "Ossuary: 9th reward": "Tears of Atonement (2500)", + "Ossuary: 10th reward": "Tears of Atonement (3000)", + "Ossuary: 11th reward": "Tears of Atonement (5000)", +} + +boss_dict: Dict[str, str] = { + "BotTC: Esdras, of the Anointed Legion": "Tears of Atonement (4300)", + "BotSS: Warden of the Silent Sorrow": "Tears of Atonement (300)", + "CoOLotCV: Our Lady of the Charred Visage": "Tears of Atonement (2600)", + "HotD: Laudes, the First of the Amanecidas": "Tears of Atonement (30000)", + "GotP: Amanecida of the Bejeweled Arrow": "Tears of Atonement (18000)", + "GA: Tres Angustias": "Tears of Atonement (2100)", + "MD: Ten Piedad": "Tears of Atonement (625)", + "MoM: Melquiades, The Exhumed Archbishop": "Tears of Atonement (5500)", + "MotED: Amanecida of the Golden Blades": "Tears of Atonement (18000)", + "MaH: Sierpes": "Tears of Atonement (5000)", + "PotSS: Amanecida of the Chiselled Steel": "Tears of Atonement (18000)", + "TSC: Exposito, Scion of Abjuration": "Tears of Atonement (9000)", + "WotHP: Quirce, Returned By The Flames": "Tears of Atonement (11250)", + "WotHP: Amanecida of the Molten Thorn": "Tears of Atonement (18000)" +} + +wound_dict: Dict[str, str] = { + "CoOLotCV: Visage of Compunction": "Holy Wound of Compunction", + "GA: Visage of Contrition": "Holy Wound of Contrition", + "MD: Visage of Attrition": "Holy Wound of Attrition" +} + +mask_dict: Dict[str, str] = { + "CoOLotCV: Mask room": "Mirrored Mask of Dolphos", + "LotNW: Mask room": "Embossed Mask of Crescente", + "MoM: Mask room": "Deformed Mask of Orestes" +} + +eye_dict: Dict[str, str] = { + "Ossuary: Isidora, Voice of the Dead": "Severed Right Eye of the Traitor", + "MaH: Sierpes' eye": "Broken Left Eye of the Traitor" +} + +herb_dict: Dict[str, str] = { + "Albero: Gate of Travel room": "Bouquet of Thyme", + "Jondo: Lower east bell trap": "Bouquet of Rosemary", + "MotED: Blood platform alcove": "Dried Clove", + "PotSS: Third area lower ledge": "Olive Seeds", + "TSC: Painting ladder ledge": "Sooty Garlic", + "WOTW: Entrance to tomb": "Incense Garlic" +} + +church_dict: Dict[str, str] = { + "Albero: Donate 5000 Tears": "Token of Appreciation", + "Albero: Donate 50000 Tears": "Cloistered Ruby" +} + +shop_dict: Dict[str, str] = { + "GotP: Shop item 1": "Torn Bridal Ribbon", + "GotP: Shop item 2": "Calcified Eye of Erudition", + "GotP: Shop item 3": "Ember of the Holy Cremation", + "MD: Shop item 1": "Key to the Chamber of the Eldest Brother", + "MD: Shop item 2": "Hollow Pearl", + "MD: Shop item 3": "Moss Preserved in Glass", + "TSC: Shop item 1": "Wicker Knot", + "TSC: Shop item 2": "Empty Bile Vessel", + "TSC: Shop item 3": "Key of the Inquisitor" +} + +thorn_set: Set[str] = { + "THL: Deogracias' gift", + "Confessor Dungeon 1 main", + "Confessor Dungeon 2 main", + "Confessor Dungeon 3 main", + "Confessor Dungeon 4 main", + "Confessor Dungeon 5 main", + "Confessor Dungeon 6 main", + "Confessor Dungeon 7 main", +} + +candle_dict: Dict[str, str] = { + "CoOLotCV: Red candle": "Bead of Red Wax", + "LotNW: Red candle": "Bead of Red Wax", + "MD: Red candle": "Bead of Red Wax", + "BotSS: Blue candle": "Bead of Blue Wax", + "CoOLotCV: Blue candle": "Bead of Blue Wax", + "MD: Blue candle": "Bead of Blue Wax" +} + +skill_dict: Dict[str, str] = { + "Skill 1, Tier 1": "Combo Skill", + "Skill 1, Tier 2": "Combo Skill", + "Skill 1, Tier 3": "Combo Skill", + "Skill 2, Tier 1": "Charged Skill", + "Skill 2, Tier 2": "Charged Skill", + "Skill 2, Tier 3": "Charged Skill", + "Skill 3, Tier 1": "Ranged Skill", + "Skill 3, Tier 2": "Ranged Skill", + "Skill 3, Tier 3": "Ranged Skill", + "Skill 4, Tier 1": "Dive Skill", + "Skill 4, Tier 2": "Dive Skill", + "Skill 4, Tier 3": "Dive Skill", + "Skill 5, Tier 1": "Lunge Skill", + "Skill 5, Tier 2": "Lunge Skill", + "Skill 5, Tier 3": "Lunge Skill", +} \ No newline at end of file diff --git a/worlds/blasphemous/__init__.py b/worlds/blasphemous/__init__.py new file mode 100644 index 00000000..70aea1ef --- /dev/null +++ b/worlds/blasphemous/__init__.py @@ -0,0 +1,413 @@ +from typing import Dict, Set, Any +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() + data_version: 1 + + 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) + + + def generate_basic(self): + 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" \ No newline at end of file diff --git a/worlds/blasphemous/docs/en_Blasphemous.md b/worlds/blasphemous/docs/en_Blasphemous.md new file mode 100644 index 00000000..15223213 --- /dev/null +++ b/worlds/blasphemous/docs/en_Blasphemous.md @@ -0,0 +1,64 @@ +# Blasphemous + +## Where is the settings page? + +The [player settings page for this game](../player-settings) contains all the options you need to configure and export a config file. + +## What does randomization do to this game? + +All items that appear on the ground are randomized, and there are options to randomize more of the game, such as stat upgrades, enemies, skills, and more. + +In addition, there are other changes to the game that make it better optimized for a randomizer: + +- Some items and enemies are never randomized. +- Teleportation between Prie Dieus can be unlocked from the beginning. +- New save files are created in True Torment mode (NG+), but enemies and bosses will use their regular attack & defense values. A penitence can be chosen if the option is enabled. +- Save files can not be ascended - the randomizer is meant to be completed in a single playthrough. +- The Ossuary will give a reward for every four bones collected. +- Side quests have been modified so that the items received from them cannot be missed. +- The Apodictic Heart of Mea Culpa can be unequipped. +- Dying with the Immaculate Bead is unnecessary, it is automatically upgraded to the Weight of True Guilt. +- If the option is enabled, the 34 corpses in game will have their messages changed to give hints about certain items and locations. The Shroud of Dreamt Sins is not required to hear them. + +## What has been changed about the side quests? + +Tirso: +- Tirso's helpers will never die. Herbs can be given to him at any time. + +Gemino: +- Gemino will never freeze. The thimble can be given to him at any time. + +Viridiana: +- Viridiana will never die. The player can ask for her assistance at all 5 boss fights, and she will still appear at the rooftops. + +Redento: +- No changes. + +Cleofas: +- The choice to end Socorro's suffering has been removed. +- Cleofas will not jump off the rooftops, even after talking to him without the Cord of the True Burying. + +Crisanta / Ending C: +- The Incomplete Scapular will not skip the fight with Esdras. Instead, it is required to open the door to the church in Brotherhood of the Silent Sorrow. +- Perpetva's item from The Resting Place of the Sister is always accessible, even after defeating Esdras. +- Crisanta's gift in Brotherhood of the Silent Sorrow will always be the Holy Wound of Abnegation. +- When fighting Crisanta, it is no longer required to have the Apodictic Heart of Mea Culpa equipped to continue with Ending C, it just needs to be in the player's inventory. + +## Which items and enemies are never randomized? + +Items: +- Golden Thimble Filled with Burning Oil - from the fountain of burning oil in Convent of Our Lady of the Charred Visage +- Hatched Egg of Deformity - from the tree in Mountains of the Endless Dusk +- Chalice of Inverted Verses - from the statue in Desecrated Cistern +- Holy Wound of Abnegation - given by Crisanta in Brotherhood of the Silent Sorrow + +Enemies: +- The Charging Knell in Mountains of the Endless Dusk +- The bell ringer in lower east Jondo +- The first Phalaris, Lionheart, and Sleepless Tomb in their respective areas (Chalice of Inverted Verses quest) + +In addition, any enemies that appear in some kind of arena (such as the Confessor Dungeons, or the bridges in Archcathedral Rooftops or Grievance Ascends) will not be randomized to prevent softlocking. + +## What does another world's item look like in Blasphemous? + +Items retain their original appearance. You won't know if an item is for another player until you collect it. The only exception to this is the shops, where items that belong to other players are represented by the Archipelago logo. \ No newline at end of file diff --git a/worlds/blasphemous/docs/setup_en.md b/worlds/blasphemous/docs/setup_en.md new file mode 100644 index 00000000..35b8670f --- /dev/null +++ b/worlds/blasphemous/docs/setup_en.md @@ -0,0 +1,21 @@ +# Blasphemous Multiworld Setup Guide + +## Required Software + +- Blasphemous from: [Steam](https://store.steampowered.com/app/774361/Blasphemous/) +- Blasphemous Modding API from: [GitHub](https://github.com/BrandenEK/Blasphemous-Modding-API) +- Blasphemous Randomizer from: [GitHub](https://github.com/BrandenEK/Blasphemous-Randomizer) +- Blasphemous Multiworld from: [GitHub](https://github.com/BrandenEK/Blasphemous-Multiworld) + +## Instructions (Windows) + +1. Download the [Modding API](https://github.com/BrandenEK/Blasphemous-Modding-API/releases), and follow the [installation instructions](https://github.com/BrandenEK/Blasphemous-Modding-API#installation) on the GitHub page. + +2. After the Modding API has been installed, download the [Randomizer](https://github.com/BrandenEK/Blasphemous-Randomizer/releases) and [Multiworld](https://github.com/BrandenEK/Blasphemous-Multiworld/releases) archives, and extract the contents of both into the `Modding` folder. + +3. Start Blasphemous. To verfy that the mods are working, look for a version number for both the Randomizer and Multiworld on the title screen. + +## Connecting + +To connect to an Archipelago server, open the in-game console by pressing backslash `\` and use the command `multiworld connect [address:port] [name] [password]`. The port and password are both optional - if no port is provided then the default port of 38281 is used. +**Make sure to connect to the server before attempting to start a new save file.** \ No newline at end of file