Heretic: implement new game (#2256)

This commit is contained in:
David St-Louis 2023-11-25 09:22:30 -05:00 committed by GitHub
parent ba53278147
commit 9afca87045
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 12049 additions and 1 deletions

View File

@ -55,7 +55,7 @@ Currently, the following games are supported:
* Pokémon Emerald
* DOOM II
* Shivers
* Heretic
For setup and instructions check out our [tutorials page](https://archipelago.gg/tutorial/).
Downloads can be found at [Releases](https://github.com/ArchipelagoMW/Archipelago/releases), including compiled

View File

@ -55,6 +55,9 @@
# Final Fantasy
/worlds/ff1/ @jtoyoda
# Heretic
/worlds/heretic/ @Daivuk
# Hollow Knight
/worlds/hk/ @BadMagic100 @ThePhar

1606
worlds/heretic/Items.py Normal file

File diff suppressed because it is too large Load Diff

8229
worlds/heretic/Locations.py Normal file

File diff suppressed because it is too large Load Diff

52
worlds/heretic/Maps.py Normal file
View File

@ -0,0 +1,52 @@
# This file is auto generated. More info: https://github.com/Daivuk/apdoom
from typing import List
map_names: List[str] = [
'The Docks (E1M1)',
'The Dungeons (E1M2)',
'The Gatehouse (E1M3)',
'The Guard Tower (E1M4)',
'The Citadel (E1M5)',
'The Cathedral (E1M6)',
'The Crypts (E1M7)',
"Hell's Maw (E1M8)",
'The Graveyard (E1M9)',
'The Crater (E2M1)',
'The Lava Pits (E2M2)',
'The River of Fire (E2M3)',
'The Ice Grotto (E2M4)',
'The Catacombs (E2M5)',
'The Labyrinth (E2M6)',
'The Great Hall (E2M7)',
'The Portals of Chaos (E2M8)',
'The Glacier (E2M9)',
'The Storehouse (E3M1)',
'The Cesspool (E3M2)',
'The Confluence (E3M3)',
'The Azure Fortress (E3M4)',
'The Ophidian Lair (E3M5)',
'The Halls of Fear (E3M6)',
'The Chasm (E3M7)',
"D'Sparil'S Keep (E3M8)",
'The Aquifier (E3M9)',
'Catafalque (E4M1)',
'Blockhouse (E4M2)',
'Ambulatory (E4M3)',
'Sepulcher (E4M4)',
'Great Stair (E4M5)',
'Halls of the Apostate (E4M6)',
'Ramparts of Perdition (E4M7)',
'Shattered Bridge (E4M8)',
'Mausoleum (E4M9)',
'Ochre Cliffs (E5M1)',
'Rapids (E5M2)',
'Quay (E5M3)',
'Courtyard (E5M4)',
'Hydratyr (E5M5)',
'Colonnade (E5M6)',
'Foetid Manse (E5M7)',
'Field of Judgement (E5M8)',
"Skein of D'Sparil (E5M9)",
]

167
worlds/heretic/Options.py Normal file
View File

@ -0,0 +1,167 @@
import typing
from Options import AssembleOptions, Choice, Toggle, DeathLink, DefaultOnToggle, StartInventoryPool
class Goal(Choice):
"""
Choose the main goal.
complete_all_levels: All levels of the selected episodes
complete_boss_levels: Boss levels (E#M8) of selected episodes
"""
display_name = "Goal"
option_complete_all_levels = 0
option_complete_boss_levels = 1
default = 0
class Difficulty(Choice):
"""
Choose the difficulty option. Those match DOOM's difficulty options.
baby (I'm too young to die.) double ammos, half damage, less monsters or strength.
easy (Hey, not too rough.) less monsters or strength.
medium (Hurt me plenty.) Default.
hard (Ultra-Violence.) More monsters or strength.
nightmare (Nightmare!) Monsters attack more rapidly and respawn.
wet nurse (hou needeth a wet-nurse) - Fewer monsters and more items than medium. Damage taken is halved, and ammo pickups carry twice as much ammo. Any Quartz Flasks and Mystic Urns are automatically used when the player nears death.
easy (Yellowbellies-r-us) - Fewer monsters and more items than medium.
medium (Bringest them oneth) - Completely balanced, this is the standard difficulty level.
hard (Thou art a smite-meister) - More monsters and fewer items than medium.
black plague (Black plague possesses thee) - Same as hard, but monsters and their projectiles move much faster. Cheating is also disabled.
"""
display_name = "Difficulty"
option_wet_nurse = 0
option_easy = 1
option_medium = 2
option_hard = 3
option_black_plague = 4
default = 2
class RandomMonsters(Choice):
"""
Choose how monsters are randomized.
vanilla: No randomization
shuffle: Monsters are shuffled within the level
random_balanced: Monsters are completely randomized, but balanced based on existing ratio in the level. (Small monsters vs medium vs big)
random_chaotic: Monsters are completely randomized, but balanced based on existing ratio in the entire game.
"""
display_name = "Random Monsters"
option_vanilla = 0
option_shuffle = 1
option_random_balanced = 2
option_random_chaotic = 3
default = 1
class RandomPickups(Choice):
"""
Choose how pickups are randomized.
vanilla: No randomization
shuffle: Pickups are shuffled within the level
random_balanced: Pickups are completely randomized, but balanced based on existing ratio in the level. (Small pickups vs Big)
"""
display_name = "Random Pickups"
option_vanilla = 0
option_shuffle = 1
option_random_balanced = 2
default = 1
class RandomMusic(Choice):
"""
Level musics will be randomized.
vanilla: No randomization
shuffle_selected: Selected episodes' levels will be shuffled
shuffle_game: All the music will be shuffled
"""
display_name = "Random Music"
option_vanilla = 0
option_shuffle_selected = 1
option_shuffle_game = 2
default = 0
class AllowDeathLogic(Toggle):
"""Some locations require a timed puzzle that can only be tried once.
After which, if the player failed to get it, the location cannot be checked anymore.
By default, no progression items are placed here. There is a way, hovewer, to still get them:
Get killed in the current map. The map will reset, you can now attempt the puzzle again."""
display_name = "Allow Death Logic"
class Pro(Toggle):
"""Include difficult tricks into rules. Mostly employed by speed runners.
i.e.: Leaps across to a locked area, trigger a switch behind a window at the right angle, etc."""
display_name = "Pro Heretic"
class StartWithMapScrolls(Toggle):
"""Give the player all Map Scroll items from the start."""
display_name = "Start With Map Scrolls"
class ResetLevelOnDeath(DefaultOnToggle):
"""When dying, levels are reset and monsters respawned. But inventory and checks are kept.
Turning this setting off is considered easy mode. Good for new players that don't know the levels well."""
display_message="Reset level on death"
class CheckSanity(Toggle):
"""Include redundant checks. This increase total check count for the game.
i.e.: In a room, there might be 3 checks close to each other. By default, two of them will be remove.
This was done to lower the total count check for Heretic, as it is quite high compared to other games.
Check Sanity restores original checks."""
display_name = "Check Sanity"
class Episode1(DefaultOnToggle):
"""City of the Damned.
If none of the episodes are chosen, Episode 1 will be chosen by default."""
display_name = "Episode 1"
class Episode2(DefaultOnToggle):
"""Hell's Maw.
If none of the episodes are chosen, Episode 1 will be chosen by default."""
display_name = "Episode 2"
class Episode3(DefaultOnToggle):
"""The Dome of D'Sparil.
If none of the episodes are chosen, Episode 1 will be chosen by default."""
display_name = "Episode 3"
class Episode4(Toggle):
"""The Ossuary.
If none of the episodes are chosen, Episode 1 will be chosen by default."""
display_name = "Episode 4"
class Episode5(Toggle):
"""The Stagnant Demesne.
If none of the episodes are chosen, Episode 1 will be chosen by default."""
display_name = "Episode 5"
options: typing.Dict[str, AssembleOptions] = {
"start_inventory_from_pool": StartInventoryPool,
"goal": Goal,
"difficulty": Difficulty,
"random_monsters": RandomMonsters,
"random_pickups": RandomPickups,
"random_music": RandomMusic,
"allow_death_logic": AllowDeathLogic,
"pro": Pro,
"check_sanity": CheckSanity,
"start_with_map_scrolls": StartWithMapScrolls,
"reset_level_on_death": ResetLevelOnDeath,
"death_link": DeathLink,
"episode1": Episode1,
"episode2": Episode2,
"episode3": Episode3,
"episode4": Episode4,
"episode5": Episode5
}

894
worlds/heretic/Regions.py Normal file
View File

@ -0,0 +1,894 @@
# This file is auto generated. More info: https://github.com/Daivuk/apdoom
from typing import List
from BaseClasses import TypedDict
class ConnectionDict(TypedDict, total=False):
target: str
pro: bool
class RegionDict(TypedDict, total=False):
name: str
connects_to_hub: bool
episode: int
connections: List[ConnectionDict]
regions:List[RegionDict] = [
# The Docks (E1M1)
{"name":"The Docks (E1M1) Main",
"connects_to_hub":True,
"episode":1,
"connections":[{"target":"The Docks (E1M1) Yellow","pro":False}]},
{"name":"The Docks (E1M1) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Docks (E1M1) Main","pro":False},
{"target":"The Docks (E1M1) Sea","pro":False}]},
{"name":"The Docks (E1M1) Sea",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Docks (E1M1) Main","pro":False}]},
# The Dungeons (E1M2)
{"name":"The Dungeons (E1M2) Main",
"connects_to_hub":True,
"episode":1,
"connections":[
{"target":"The Dungeons (E1M2) Yellow","pro":False},
{"target":"The Dungeons (E1M2) Green","pro":False}]},
{"name":"The Dungeons (E1M2) Blue",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Dungeons (E1M2) Yellow","pro":False}]},
{"name":"The Dungeons (E1M2) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Dungeons (E1M2) Main","pro":False},
{"target":"The Dungeons (E1M2) Blue","pro":False}]},
{"name":"The Dungeons (E1M2) Green",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Dungeons (E1M2) Main","pro":False},
{"target":"The Dungeons (E1M2) Yellow","pro":False}]},
# The Gatehouse (E1M3)
{"name":"The Gatehouse (E1M3) Main",
"connects_to_hub":True,
"episode":1,
"connections":[
{"target":"The Gatehouse (E1M3) Yellow","pro":False},
{"target":"The Gatehouse (E1M3) Sea","pro":False},
{"target":"The Gatehouse (E1M3) Green","pro":False}]},
{"name":"The Gatehouse (E1M3) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Gatehouse (E1M3) Main","pro":False}]},
{"name":"The Gatehouse (E1M3) Green",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Gatehouse (E1M3) Main","pro":False}]},
{"name":"The Gatehouse (E1M3) Sea",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Gatehouse (E1M3) Main","pro":False}]},
# The Guard Tower (E1M4)
{"name":"The Guard Tower (E1M4) Main",
"connects_to_hub":True,
"episode":1,
"connections":[{"target":"The Guard Tower (E1M4) Yellow","pro":False}]},
{"name":"The Guard Tower (E1M4) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Guard Tower (E1M4) Green","pro":False},
{"target":"The Guard Tower (E1M4) Main","pro":False}]},
{"name":"The Guard Tower (E1M4) Green",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Guard Tower (E1M4) Yellow","pro":False}]},
# The Citadel (E1M5)
{"name":"The Citadel (E1M5) Main",
"connects_to_hub":True,
"episode":1,
"connections":[{"target":"The Citadel (E1M5) Yellow","pro":False}]},
{"name":"The Citadel (E1M5) Blue",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Citadel (E1M5) Green","pro":False}]},
{"name":"The Citadel (E1M5) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Citadel (E1M5) Main","pro":False},
{"target":"The Citadel (E1M5) Well","pro":False},
{"target":"The Citadel (E1M5) Green","pro":False}]},
{"name":"The Citadel (E1M5) Green",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Citadel (E1M5) Main","pro":False},
{"target":"The Citadel (E1M5) Well","pro":False},
{"target":"The Citadel (E1M5) Blue","pro":False}]},
{"name":"The Citadel (E1M5) Well",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Citadel (E1M5) Main","pro":False}]},
# The Cathedral (E1M6)
{"name":"The Cathedral (E1M6) Main",
"connects_to_hub":True,
"episode":1,
"connections":[{"target":"The Cathedral (E1M6) Yellow","pro":False}]},
{"name":"The Cathedral (E1M6) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Cathedral (E1M6) Green","pro":False},
{"target":"The Cathedral (E1M6) Main","pro":False},
{"target":"The Cathedral (E1M6) Main Fly","pro":False}]},
{"name":"The Cathedral (E1M6) Green",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Cathedral (E1M6) Yellow","pro":False},
{"target":"The Cathedral (E1M6) Main Fly","pro":False}]},
{"name":"The Cathedral (E1M6) Main Fly",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Cathedral (E1M6) Main","pro":False}]},
# The Crypts (E1M7)
{"name":"The Crypts (E1M7) Main",
"connects_to_hub":True,
"episode":1,
"connections":[
{"target":"The Crypts (E1M7) Yellow","pro":False},
{"target":"The Crypts (E1M7) Green","pro":False}]},
{"name":"The Crypts (E1M7) Blue",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Crypts (E1M7) Yellow","pro":False},
{"target":"The Crypts (E1M7) Main","pro":False}]},
{"name":"The Crypts (E1M7) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Crypts (E1M7) Main","pro":False},
{"target":"The Crypts (E1M7) Green","pro":False},
{"target":"The Crypts (E1M7) Blue","pro":False}]},
{"name":"The Crypts (E1M7) Green",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Crypts (E1M7) Yellow","pro":False},
{"target":"The Crypts (E1M7) Main","pro":False}]},
# Hell's Maw (E1M8)
{"name":"Hell's Maw (E1M8) Main",
"connects_to_hub":True,
"episode":1,
"connections":[]},
# The Graveyard (E1M9)
{"name":"The Graveyard (E1M9) Main",
"connects_to_hub":True,
"episode":1,
"connections":[
{"target":"The Graveyard (E1M9) Yellow","pro":False},
{"target":"The Graveyard (E1M9) Green","pro":False},
{"target":"The Graveyard (E1M9) Blue","pro":False}]},
{"name":"The Graveyard (E1M9) Blue",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Graveyard (E1M9) Main","pro":False}]},
{"name":"The Graveyard (E1M9) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Graveyard (E1M9) Main","pro":False}]},
{"name":"The Graveyard (E1M9) Green",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Graveyard (E1M9) Main","pro":False}]},
# The Crater (E2M1)
{"name":"The Crater (E2M1) Main",
"connects_to_hub":True,
"episode":2,
"connections":[{"target":"The Crater (E2M1) Yellow","pro":False}]},
{"name":"The Crater (E2M1) Yellow",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"The Crater (E2M1) Main","pro":False},
{"target":"The Crater (E2M1) Green","pro":False}]},
{"name":"The Crater (E2M1) Green",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Crater (E2M1) Yellow","pro":False}]},
# The Lava Pits (E2M2)
{"name":"The Lava Pits (E2M2) Main",
"connects_to_hub":True,
"episode":2,
"connections":[{"target":"The Lava Pits (E2M2) Yellow","pro":False}]},
{"name":"The Lava Pits (E2M2) Yellow",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"The Lava Pits (E2M2) Green","pro":False},
{"target":"The Lava Pits (E2M2) Main","pro":False}]},
{"name":"The Lava Pits (E2M2) Green",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"The Lava Pits (E2M2) Main","pro":False},
{"target":"The Lava Pits (E2M2) Yellow","pro":False}]},
# The River of Fire (E2M3)
{"name":"The River of Fire (E2M3) Main",
"connects_to_hub":True,
"episode":2,
"connections":[
{"target":"The River of Fire (E2M3) Yellow","pro":False},
{"target":"The River of Fire (E2M3) Blue","pro":False},
{"target":"The River of Fire (E2M3) Green","pro":False}]},
{"name":"The River of Fire (E2M3) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The River of Fire (E2M3) Main","pro":False}]},
{"name":"The River of Fire (E2M3) Yellow",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The River of Fire (E2M3) Main","pro":False}]},
{"name":"The River of Fire (E2M3) Green",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The River of Fire (E2M3) Main","pro":False}]},
# The Ice Grotto (E2M4)
{"name":"The Ice Grotto (E2M4) Main",
"connects_to_hub":True,
"episode":2,
"connections":[
{"target":"The Ice Grotto (E2M4) Green","pro":False},
{"target":"The Ice Grotto (E2M4) Yellow","pro":False}]},
{"name":"The Ice Grotto (E2M4) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Ice Grotto (E2M4) Green","pro":False}]},
{"name":"The Ice Grotto (E2M4) Yellow",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"The Ice Grotto (E2M4) Main","pro":False},
{"target":"The Ice Grotto (E2M4) Magenta","pro":False}]},
{"name":"The Ice Grotto (E2M4) Green",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"The Ice Grotto (E2M4) Main","pro":False},
{"target":"The Ice Grotto (E2M4) Blue","pro":False}]},
{"name":"The Ice Grotto (E2M4) Magenta",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Ice Grotto (E2M4) Yellow","pro":False}]},
# The Catacombs (E2M5)
{"name":"The Catacombs (E2M5) Main",
"connects_to_hub":True,
"episode":2,
"connections":[{"target":"The Catacombs (E2M5) Yellow","pro":False}]},
{"name":"The Catacombs (E2M5) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Catacombs (E2M5) Green","pro":False}]},
{"name":"The Catacombs (E2M5) Yellow",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"The Catacombs (E2M5) Green","pro":False},
{"target":"The Catacombs (E2M5) Main","pro":False}]},
{"name":"The Catacombs (E2M5) Green",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"The Catacombs (E2M5) Blue","pro":False},
{"target":"The Catacombs (E2M5) Yellow","pro":False},
{"target":"The Catacombs (E2M5) Main","pro":False}]},
# The Labyrinth (E2M6)
{"name":"The Labyrinth (E2M6) Main",
"connects_to_hub":True,
"episode":2,
"connections":[
{"target":"The Labyrinth (E2M6) Blue","pro":False},
{"target":"The Labyrinth (E2M6) Yellow","pro":False},
{"target":"The Labyrinth (E2M6) Green","pro":False}]},
{"name":"The Labyrinth (E2M6) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Labyrinth (E2M6) Main","pro":False}]},
{"name":"The Labyrinth (E2M6) Yellow",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Labyrinth (E2M6) Main","pro":False}]},
{"name":"The Labyrinth (E2M6) Green",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Labyrinth (E2M6) Main","pro":False}]},
# The Great Hall (E2M7)
{"name":"The Great Hall (E2M7) Main",
"connects_to_hub":True,
"episode":2,
"connections":[
{"target":"The Great Hall (E2M7) Yellow","pro":False},
{"target":"The Great Hall (E2M7) Green","pro":False}]},
{"name":"The Great Hall (E2M7) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Great Hall (E2M7) Yellow","pro":False}]},
{"name":"The Great Hall (E2M7) Yellow",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"The Great Hall (E2M7) Blue","pro":False},
{"target":"The Great Hall (E2M7) Main","pro":False}]},
{"name":"The Great Hall (E2M7) Green",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Great Hall (E2M7) Main","pro":False}]},
# The Portals of Chaos (E2M8)
{"name":"The Portals of Chaos (E2M8) Main",
"connects_to_hub":True,
"episode":2,
"connections":[]},
# The Glacier (E2M9)
{"name":"The Glacier (E2M9) Main",
"connects_to_hub":True,
"episode":2,
"connections":[
{"target":"The Glacier (E2M9) Yellow","pro":False},
{"target":"The Glacier (E2M9) Blue","pro":False},
{"target":"The Glacier (E2M9) Green","pro":False}]},
{"name":"The Glacier (E2M9) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Glacier (E2M9) Main","pro":False}]},
{"name":"The Glacier (E2M9) Yellow",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Glacier (E2M9) Main","pro":False}]},
{"name":"The Glacier (E2M9) Green",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Glacier (E2M9) Main","pro":False}]},
# The Storehouse (E3M1)
{"name":"The Storehouse (E3M1) Main",
"connects_to_hub":True,
"episode":3,
"connections":[
{"target":"The Storehouse (E3M1) Yellow","pro":False},
{"target":"The Storehouse (E3M1) Green","pro":False}]},
{"name":"The Storehouse (E3M1) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Storehouse (E3M1) Main","pro":False}]},
{"name":"The Storehouse (E3M1) Green",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Storehouse (E3M1) Main","pro":False}]},
# The Cesspool (E3M2)
{"name":"The Cesspool (E3M2) Main",
"connects_to_hub":True,
"episode":3,
"connections":[{"target":"The Cesspool (E3M2) Yellow","pro":False}]},
{"name":"The Cesspool (E3M2) Blue",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Cesspool (E3M2) Green","pro":False}]},
{"name":"The Cesspool (E3M2) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[
{"target":"The Cesspool (E3M2) Main","pro":False},
{"target":"The Cesspool (E3M2) Green","pro":False}]},
{"name":"The Cesspool (E3M2) Green",
"connects_to_hub":False,
"episode":3,
"connections":[
{"target":"The Cesspool (E3M2) Blue","pro":False},
{"target":"The Cesspool (E3M2) Main","pro":False},
{"target":"The Cesspool (E3M2) Yellow","pro":False}]},
# The Confluence (E3M3)
{"name":"The Confluence (E3M3) Main",
"connects_to_hub":True,
"episode":3,
"connections":[
{"target":"The Confluence (E3M3) Green","pro":False},
{"target":"The Confluence (E3M3) Yellow","pro":False}]},
{"name":"The Confluence (E3M3) Blue",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Confluence (E3M3) Green","pro":False}]},
{"name":"The Confluence (E3M3) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Confluence (E3M3) Main","pro":False}]},
{"name":"The Confluence (E3M3) Green",
"connects_to_hub":False,
"episode":3,
"connections":[
{"target":"The Confluence (E3M3) Main","pro":False},
{"target":"The Confluence (E3M3) Blue","pro":False},
{"target":"The Confluence (E3M3) Yellow","pro":False}]},
# The Azure Fortress (E3M4)
{"name":"The Azure Fortress (E3M4) Main",
"connects_to_hub":True,
"episode":3,
"connections":[
{"target":"The Azure Fortress (E3M4) Green","pro":False},
{"target":"The Azure Fortress (E3M4) Yellow","pro":False}]},
{"name":"The Azure Fortress (E3M4) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Azure Fortress (E3M4) Main","pro":False}]},
{"name":"The Azure Fortress (E3M4) Green",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Azure Fortress (E3M4) Main","pro":False}]},
# The Ophidian Lair (E3M5)
{"name":"The Ophidian Lair (E3M5) Main",
"connects_to_hub":True,
"episode":3,
"connections":[
{"target":"The Ophidian Lair (E3M5) Yellow","pro":False},
{"target":"The Ophidian Lair (E3M5) Green","pro":False}]},
{"name":"The Ophidian Lair (E3M5) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Ophidian Lair (E3M5) Main","pro":False}]},
{"name":"The Ophidian Lair (E3M5) Green",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Ophidian Lair (E3M5) Main","pro":False}]},
# The Halls of Fear (E3M6)
{"name":"The Halls of Fear (E3M6) Main",
"connects_to_hub":True,
"episode":3,
"connections":[{"target":"The Halls of Fear (E3M6) Yellow","pro":False}]},
{"name":"The Halls of Fear (E3M6) Blue",
"connects_to_hub":False,
"episode":3,
"connections":[
{"target":"The Halls of Fear (E3M6) Yellow","pro":False},
{"target":"The Halls of Fear (E3M6) Cyan","pro":False}]},
{"name":"The Halls of Fear (E3M6) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[
{"target":"The Halls of Fear (E3M6) Blue","pro":False},
{"target":"The Halls of Fear (E3M6) Main","pro":False},
{"target":"The Halls of Fear (E3M6) Green","pro":False}]},
{"name":"The Halls of Fear (E3M6) Green",
"connects_to_hub":False,
"episode":3,
"connections":[
{"target":"The Halls of Fear (E3M6) Yellow","pro":False},
{"target":"The Halls of Fear (E3M6) Main","pro":False},
{"target":"The Halls of Fear (E3M6) Cyan","pro":False}]},
{"name":"The Halls of Fear (E3M6) Cyan",
"connects_to_hub":False,
"episode":3,
"connections":[
{"target":"The Halls of Fear (E3M6) Yellow","pro":False},
{"target":"The Halls of Fear (E3M6) Main","pro":False}]},
# The Chasm (E3M7)
{"name":"The Chasm (E3M7) Main",
"connects_to_hub":True,
"episode":3,
"connections":[{"target":"The Chasm (E3M7) Yellow","pro":False}]},
{"name":"The Chasm (E3M7) Blue",
"connects_to_hub":False,
"episode":3,
"connections":[]},
{"name":"The Chasm (E3M7) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[
{"target":"The Chasm (E3M7) Main","pro":False},
{"target":"The Chasm (E3M7) Green","pro":False},
{"target":"The Chasm (E3M7) Blue","pro":False}]},
{"name":"The Chasm (E3M7) Green",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Chasm (E3M7) Yellow","pro":False}]},
# D'Sparil'S Keep (E3M8)
{"name":"D'Sparil'S Keep (E3M8) Main",
"connects_to_hub":True,
"episode":3,
"connections":[]},
# The Aquifier (E3M9)
{"name":"The Aquifier (E3M9) Main",
"connects_to_hub":True,
"episode":3,
"connections":[{"target":"The Aquifier (E3M9) Yellow","pro":False}]},
{"name":"The Aquifier (E3M9) Blue",
"connects_to_hub":False,
"episode":3,
"connections":[]},
{"name":"The Aquifier (E3M9) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[
{"target":"The Aquifier (E3M9) Green","pro":False},
{"target":"The Aquifier (E3M9) Main","pro":False}]},
{"name":"The Aquifier (E3M9) Green",
"connects_to_hub":False,
"episode":3,
"connections":[
{"target":"The Aquifier (E3M9) Yellow","pro":False},
{"target":"The Aquifier (E3M9) Main","pro":False},
{"target":"The Aquifier (E3M9) Blue","pro":False}]},
# Catafalque (E4M1)
{"name":"Catafalque (E4M1) Main",
"connects_to_hub":True,
"episode":4,
"connections":[{"target":"Catafalque (E4M1) Yellow","pro":False}]},
{"name":"Catafalque (E4M1) Yellow",
"connects_to_hub":False,
"episode":4,
"connections":[
{"target":"Catafalque (E4M1) Green","pro":False},
{"target":"Catafalque (E4M1) Main","pro":False}]},
{"name":"Catafalque (E4M1) Green",
"connects_to_hub":False,
"episode":4,
"connections":[{"target":"Catafalque (E4M1) Main","pro":False}]},
# Blockhouse (E4M2)
{"name":"Blockhouse (E4M2) Main",
"connects_to_hub":True,
"episode":4,
"connections":[
{"target":"Blockhouse (E4M2) Yellow","pro":False},
{"target":"Blockhouse (E4M2) Green","pro":False},
{"target":"Blockhouse (E4M2) Blue","pro":False}]},
{"name":"Blockhouse (E4M2) Yellow",
"connects_to_hub":False,
"episode":4,
"connections":[
{"target":"Blockhouse (E4M2) Main","pro":False},
{"target":"Blockhouse (E4M2) Balcony","pro":False},
{"target":"Blockhouse (E4M2) Lake","pro":False}]},
{"name":"Blockhouse (E4M2) Green",
"connects_to_hub":False,
"episode":4,
"connections":[{"target":"Blockhouse (E4M2) Main","pro":False}]},
{"name":"Blockhouse (E4M2) Blue",
"connects_to_hub":False,
"episode":4,
"connections":[{"target":"Blockhouse (E4M2) Main","pro":False}]},
{"name":"Blockhouse (E4M2) Lake",
"connects_to_hub":False,
"episode":4,
"connections":[{"target":"Blockhouse (E4M2) Balcony","pro":False}]},
{"name":"Blockhouse (E4M2) Balcony",
"connects_to_hub":False,
"episode":4,
"connections":[]},
# Ambulatory (E4M3)
{"name":"Ambulatory (E4M3) Main",
"connects_to_hub":True,
"episode":4,
"connections":[
{"target":"Ambulatory (E4M3) Blue","pro":False},
{"target":"Ambulatory (E4M3) Yellow","pro":False},
{"target":"Ambulatory (E4M3) Green","pro":False}]},
{"name":"Ambulatory (E4M3) Blue",
"connects_to_hub":False,
"episode":4,
"connections":[
{"target":"Ambulatory (E4M3) Yellow","pro":False},
{"target":"Ambulatory (E4M3) Green","pro":False}]},
{"name":"Ambulatory (E4M3) Yellow",
"connects_to_hub":False,
"episode":4,
"connections":[{"target":"Ambulatory (E4M3) Main","pro":False}]},
{"name":"Ambulatory (E4M3) Green",
"connects_to_hub":False,
"episode":4,
"connections":[{"target":"Ambulatory (E4M3) Main","pro":False}]},
# Sepulcher (E4M4)
{"name":"Sepulcher (E4M4) Main",
"connects_to_hub":True,
"episode":4,
"connections":[]},
# Great Stair (E4M5)
{"name":"Great Stair (E4M5) Main",
"connects_to_hub":True,
"episode":4,
"connections":[{"target":"Great Stair (E4M5) Yellow","pro":False}]},
{"name":"Great Stair (E4M5) Blue",
"connects_to_hub":False,
"episode":4,
"connections":[{"target":"Great Stair (E4M5) Green","pro":False}]},
{"name":"Great Stair (E4M5) Yellow",
"connects_to_hub":False,
"episode":4,
"connections":[
{"target":"Great Stair (E4M5) Main","pro":False},
{"target":"Great Stair (E4M5) Green","pro":False}]},
{"name":"Great Stair (E4M5) Green",
"connects_to_hub":False,
"episode":4,
"connections":[
{"target":"Great Stair (E4M5) Blue","pro":False},
{"target":"Great Stair (E4M5) Yellow","pro":False}]},
# Halls of the Apostate (E4M6)
{"name":"Halls of the Apostate (E4M6) Main",
"connects_to_hub":True,
"episode":4,
"connections":[{"target":"Halls of the Apostate (E4M6) Yellow","pro":False}]},
{"name":"Halls of the Apostate (E4M6) Blue",
"connects_to_hub":False,
"episode":4,
"connections":[{"target":"Halls of the Apostate (E4M6) Green","pro":False}]},
{"name":"Halls of the Apostate (E4M6) Yellow",
"connects_to_hub":False,
"episode":4,
"connections":[
{"target":"Halls of the Apostate (E4M6) Main","pro":False},
{"target":"Halls of the Apostate (E4M6) Green","pro":False}]},
{"name":"Halls of the Apostate (E4M6) Green",
"connects_to_hub":False,
"episode":4,
"connections":[
{"target":"Halls of the Apostate (E4M6) Yellow","pro":False},
{"target":"Halls of the Apostate (E4M6) Blue","pro":False}]},
# Ramparts of Perdition (E4M7)
{"name":"Ramparts of Perdition (E4M7) Main",
"connects_to_hub":True,
"episode":4,
"connections":[{"target":"Ramparts of Perdition (E4M7) Yellow","pro":False}]},
{"name":"Ramparts of Perdition (E4M7) Blue",
"connects_to_hub":False,
"episode":4,
"connections":[{"target":"Ramparts of Perdition (E4M7) Yellow","pro":False}]},
{"name":"Ramparts of Perdition (E4M7) Yellow",
"connects_to_hub":False,
"episode":4,
"connections":[
{"target":"Ramparts of Perdition (E4M7) Main","pro":False},
{"target":"Ramparts of Perdition (E4M7) Green","pro":False},
{"target":"Ramparts of Perdition (E4M7) Blue","pro":False}]},
{"name":"Ramparts of Perdition (E4M7) Green",
"connects_to_hub":False,
"episode":4,
"connections":[{"target":"Ramparts of Perdition (E4M7) Yellow","pro":False}]},
# Shattered Bridge (E4M8)
{"name":"Shattered Bridge (E4M8) Main",
"connects_to_hub":True,
"episode":4,
"connections":[{"target":"Shattered Bridge (E4M8) Yellow","pro":False}]},
{"name":"Shattered Bridge (E4M8) Yellow",
"connects_to_hub":False,
"episode":4,
"connections":[
{"target":"Shattered Bridge (E4M8) Main","pro":False},
{"target":"Shattered Bridge (E4M8) Boss","pro":False}]},
{"name":"Shattered Bridge (E4M8) Boss",
"connects_to_hub":False,
"episode":4,
"connections":[]},
# Mausoleum (E4M9)
{"name":"Mausoleum (E4M9) Main",
"connects_to_hub":True,
"episode":4,
"connections":[{"target":"Mausoleum (E4M9) Yellow","pro":False}]},
{"name":"Mausoleum (E4M9) Yellow",
"connects_to_hub":False,
"episode":4,
"connections":[{"target":"Mausoleum (E4M9) Main","pro":False}]},
# Ochre Cliffs (E5M1)
{"name":"Ochre Cliffs (E5M1) Main",
"connects_to_hub":True,
"episode":5,
"connections":[{"target":"Ochre Cliffs (E5M1) Yellow","pro":False}]},
{"name":"Ochre Cliffs (E5M1) Blue",
"connects_to_hub":False,
"episode":5,
"connections":[{"target":"Ochre Cliffs (E5M1) Yellow","pro":False}]},
{"name":"Ochre Cliffs (E5M1) Yellow",
"connects_to_hub":False,
"episode":5,
"connections":[
{"target":"Ochre Cliffs (E5M1) Main","pro":False},
{"target":"Ochre Cliffs (E5M1) Green","pro":False},
{"target":"Ochre Cliffs (E5M1) Blue","pro":False}]},
{"name":"Ochre Cliffs (E5M1) Green",
"connects_to_hub":False,
"episode":5,
"connections":[{"target":"Ochre Cliffs (E5M1) Yellow","pro":False}]},
# Rapids (E5M2)
{"name":"Rapids (E5M2) Main",
"connects_to_hub":True,
"episode":5,
"connections":[{"target":"Rapids (E5M2) Yellow","pro":False}]},
{"name":"Rapids (E5M2) Yellow",
"connects_to_hub":False,
"episode":5,
"connections":[
{"target":"Rapids (E5M2) Main","pro":False},
{"target":"Rapids (E5M2) Green","pro":False}]},
{"name":"Rapids (E5M2) Green",
"connects_to_hub":False,
"episode":5,
"connections":[
{"target":"Rapids (E5M2) Yellow","pro":False},
{"target":"Rapids (E5M2) Main","pro":False}]},
# Quay (E5M3)
{"name":"Quay (E5M3) Main",
"connects_to_hub":True,
"episode":5,
"connections":[
{"target":"Quay (E5M3) Yellow","pro":False},
{"target":"Quay (E5M3) Green","pro":False},
{"target":"Quay (E5M3) Blue","pro":False}]},
{"name":"Quay (E5M3) Blue",
"connects_to_hub":False,
"episode":5,
"connections":[
{"target":"Quay (E5M3) Green","pro":False},
{"target":"Quay (E5M3) Main","pro":False}]},
{"name":"Quay (E5M3) Yellow",
"connects_to_hub":False,
"episode":5,
"connections":[{"target":"Quay (E5M3) Main","pro":False}]},
{"name":"Quay (E5M3) Green",
"connects_to_hub":False,
"episode":5,
"connections":[
{"target":"Quay (E5M3) Main","pro":False},
{"target":"Quay (E5M3) Blue","pro":False}]},
# Courtyard (E5M4)
{"name":"Courtyard (E5M4) Main",
"connects_to_hub":True,
"episode":5,
"connections":[
{"target":"Courtyard (E5M4) Kakis","pro":False},
{"target":"Courtyard (E5M4) Blue","pro":False}]},
{"name":"Courtyard (E5M4) Blue",
"connects_to_hub":False,
"episode":5,
"connections":[{"target":"Courtyard (E5M4) Main","pro":False}]},
{"name":"Courtyard (E5M4) Kakis",
"connects_to_hub":False,
"episode":5,
"connections":[{"target":"Courtyard (E5M4) Main","pro":False}]},
# Hydratyr (E5M5)
{"name":"Hydratyr (E5M5) Main",
"connects_to_hub":True,
"episode":5,
"connections":[{"target":"Hydratyr (E5M5) Yellow","pro":False}]},
{"name":"Hydratyr (E5M5) Blue",
"connects_to_hub":False,
"episode":5,
"connections":[{"target":"Hydratyr (E5M5) Green","pro":False}]},
{"name":"Hydratyr (E5M5) Yellow",
"connects_to_hub":False,
"episode":5,
"connections":[
{"target":"Hydratyr (E5M5) Main","pro":False},
{"target":"Hydratyr (E5M5) Green","pro":False}]},
{"name":"Hydratyr (E5M5) Green",
"connects_to_hub":False,
"episode":5,
"connections":[
{"target":"Hydratyr (E5M5) Main","pro":False},
{"target":"Hydratyr (E5M5) Yellow","pro":False},
{"target":"Hydratyr (E5M5) Blue","pro":False}]},
# Colonnade (E5M6)
{"name":"Colonnade (E5M6) Main",
"connects_to_hub":True,
"episode":5,
"connections":[
{"target":"Colonnade (E5M6) Yellow","pro":False},
{"target":"Colonnade (E5M6) Blue","pro":False}]},
{"name":"Colonnade (E5M6) Blue",
"connects_to_hub":False,
"episode":5,
"connections":[{"target":"Colonnade (E5M6) Main","pro":False}]},
{"name":"Colonnade (E5M6) Yellow",
"connects_to_hub":False,
"episode":5,
"connections":[
{"target":"Colonnade (E5M6) Main","pro":False},
{"target":"Colonnade (E5M6) Green","pro":False}]},
{"name":"Colonnade (E5M6) Green",
"connects_to_hub":False,
"episode":5,
"connections":[{"target":"Colonnade (E5M6) Yellow","pro":False}]},
# Foetid Manse (E5M7)
{"name":"Foetid Manse (E5M7) Main",
"connects_to_hub":True,
"episode":5,
"connections":[{"target":"Foetid Manse (E5M7) Yellow","pro":False}]},
{"name":"Foetid Manse (E5M7) Blue",
"connects_to_hub":False,
"episode":5,
"connections":[{"target":"Foetid Manse (E5M7) Yellow","pro":False}]},
{"name":"Foetid Manse (E5M7) Yellow",
"connects_to_hub":False,
"episode":5,
"connections":[
{"target":"Foetid Manse (E5M7) Main","pro":False},
{"target":"Foetid Manse (E5M7) Green","pro":False},
{"target":"Foetid Manse (E5M7) Blue","pro":False}]},
{"name":"Foetid Manse (E5M7) Green",
"connects_to_hub":False,
"episode":5,
"connections":[
{"target":"Foetid Manse (E5M7) Yellow","pro":False},
{"target":"Foetid Manse (E5M7) Main","pro":False}]},
# Field of Judgement (E5M8)
{"name":"Field of Judgement (E5M8) Main",
"connects_to_hub":True,
"episode":5,
"connections":[]},
# Skein of D'Sparil (E5M9)
{"name":"Skein of D'Sparil (E5M9) Main",
"connects_to_hub":True,
"episode":5,
"connections":[
{"target":"Skein of D'Sparil (E5M9) Blue","pro":False},
{"target":"Skein of D'Sparil (E5M9) Yellow","pro":False},
{"target":"Skein of D'Sparil (E5M9) Green","pro":False}]},
{"name":"Skein of D'Sparil (E5M9) Blue",
"connects_to_hub":False,
"episode":5,
"connections":[{"target":"Skein of D'Sparil (E5M9) Main","pro":False}]},
{"name":"Skein of D'Sparil (E5M9) Yellow",
"connects_to_hub":False,
"episode":5,
"connections":[{"target":"Skein of D'Sparil (E5M9) Main","pro":False}]},
{"name":"Skein of D'Sparil (E5M9) Green",
"connects_to_hub":False,
"episode":5,
"connections":[{"target":"Skein of D'Sparil (E5M9) Main","pro":False}]},
]

736
worlds/heretic/Rules.py Normal file
View File

@ -0,0 +1,736 @@
# This file is auto generated. More info: https://github.com/Daivuk/apdoom
from typing import TYPE_CHECKING
from worlds.generic.Rules import set_rule
if TYPE_CHECKING:
from . import HereticWorld
def set_episode1_rules(player, world, pro):
# The Docks (E1M1)
set_rule(world.get_entrance("Hub -> The Docks (E1M1) Main", player), lambda state:
state.has("The Docks (E1M1)", player, 1))
set_rule(world.get_entrance("The Docks (E1M1) Main -> The Docks (E1M1) Yellow", player), lambda state:
state.has("The Docks (E1M1) - Yellow key", player, 1))
# The Dungeons (E1M2)
set_rule(world.get_entrance("Hub -> The Dungeons (E1M2) Main", player), lambda state:
(state.has("The Dungeons (E1M2)", player, 1)) and
(state.has("Dragon Claw", player, 1) or
state.has("Ethereal Crossbow", player, 1)))
set_rule(world.get_entrance("The Dungeons (E1M2) Main -> The Dungeons (E1M2) Yellow", player), lambda state:
state.has("The Dungeons (E1M2) - Yellow key", player, 1))
set_rule(world.get_entrance("The Dungeons (E1M2) Main -> The Dungeons (E1M2) Green", player), lambda state:
state.has("The Dungeons (E1M2) - Green key", player, 1))
set_rule(world.get_entrance("The Dungeons (E1M2) Blue -> The Dungeons (E1M2) Yellow", player), lambda state:
state.has("The Dungeons (E1M2) - Blue key", player, 1))
set_rule(world.get_entrance("The Dungeons (E1M2) Yellow -> The Dungeons (E1M2) Blue", player), lambda state:
state.has("The Dungeons (E1M2) - Blue key", player, 1))
# The Gatehouse (E1M3)
set_rule(world.get_entrance("Hub -> The Gatehouse (E1M3) Main", player), lambda state:
(state.has("The Gatehouse (E1M3)", player, 1)) and
(state.has("Ethereal Crossbow", player, 1) or
state.has("Dragon Claw", player, 1)))
set_rule(world.get_entrance("The Gatehouse (E1M3) Main -> The Gatehouse (E1M3) Yellow", player), lambda state:
state.has("The Gatehouse (E1M3) - Yellow key", player, 1))
set_rule(world.get_entrance("The Gatehouse (E1M3) Main -> The Gatehouse (E1M3) Sea", player), lambda state:
state.has("The Gatehouse (E1M3) - Yellow key", player, 1))
set_rule(world.get_entrance("The Gatehouse (E1M3) Main -> The Gatehouse (E1M3) Green", player), lambda state:
state.has("The Gatehouse (E1M3) - Green key", player, 1))
set_rule(world.get_entrance("The Gatehouse (E1M3) Green -> The Gatehouse (E1M3) Main", player), lambda state:
state.has("The Gatehouse (E1M3) - Green key", player, 1))
# The Guard Tower (E1M4)
set_rule(world.get_entrance("Hub -> The Guard Tower (E1M4) Main", player), lambda state:
(state.has("The Guard Tower (E1M4)", player, 1)) and
(state.has("Ethereal Crossbow", player, 1) or
state.has("Dragon Claw", player, 1)))
set_rule(world.get_entrance("The Guard Tower (E1M4) Main -> The Guard Tower (E1M4) Yellow", player), lambda state:
state.has("The Guard Tower (E1M4) - Yellow key", player, 1))
set_rule(world.get_entrance("The Guard Tower (E1M4) Yellow -> The Guard Tower (E1M4) Green", player), lambda state:
state.has("The Guard Tower (E1M4) - Green key", player, 1))
set_rule(world.get_entrance("The Guard Tower (E1M4) Green -> The Guard Tower (E1M4) Yellow", player), lambda state:
state.has("The Guard Tower (E1M4) - Green key", player, 1))
# The Citadel (E1M5)
set_rule(world.get_entrance("Hub -> The Citadel (E1M5) Main", player), lambda state:
(state.has("The Citadel (E1M5)", player, 1) and
state.has("Ethereal Crossbow", player, 1)) and
(state.has("Dragon Claw", player, 1) or
state.has("Gauntlets of the Necromancer", player, 1)))
set_rule(world.get_entrance("The Citadel (E1M5) Main -> The Citadel (E1M5) Yellow", player), lambda state:
state.has("The Citadel (E1M5) - Yellow key", player, 1))
set_rule(world.get_entrance("The Citadel (E1M5) Blue -> The Citadel (E1M5) Green", player), lambda state:
state.has("The Citadel (E1M5) - Blue key", player, 1))
set_rule(world.get_entrance("The Citadel (E1M5) Yellow -> The Citadel (E1M5) Green", player), lambda state:
state.has("The Citadel (E1M5) - Green key", player, 1))
set_rule(world.get_entrance("The Citadel (E1M5) Green -> The Citadel (E1M5) Blue", player), lambda state:
state.has("The Citadel (E1M5) - Blue key", player, 1))
# The Cathedral (E1M6)
set_rule(world.get_entrance("Hub -> The Cathedral (E1M6) Main", player), lambda state:
(state.has("The Cathedral (E1M6)", player, 1) and
state.has("Ethereal Crossbow", player, 1)) and
(state.has("Gauntlets of the Necromancer", player, 1) or
state.has("Dragon Claw", player, 1)))
set_rule(world.get_entrance("The Cathedral (E1M6) Main -> The Cathedral (E1M6) Yellow", player), lambda state:
state.has("The Cathedral (E1M6) - Yellow key", player, 1))
set_rule(world.get_entrance("The Cathedral (E1M6) Yellow -> The Cathedral (E1M6) Green", player), lambda state:
state.has("The Cathedral (E1M6) - Green key", player, 1))
# The Crypts (E1M7)
set_rule(world.get_entrance("Hub -> The Crypts (E1M7) Main", player), lambda state:
(state.has("The Crypts (E1M7)", player, 1) and
state.has("Ethereal Crossbow", player, 1)) and
(state.has("Gauntlets of the Necromancer", player, 1) or
state.has("Dragon Claw", player, 1)))
set_rule(world.get_entrance("The Crypts (E1M7) Main -> The Crypts (E1M7) Yellow", player), lambda state:
state.has("The Crypts (E1M7) - Yellow key", player, 1))
set_rule(world.get_entrance("The Crypts (E1M7) Main -> The Crypts (E1M7) Green", player), lambda state:
state.has("The Crypts (E1M7) - Green key", player, 1))
set_rule(world.get_entrance("The Crypts (E1M7) Yellow -> The Crypts (E1M7) Green", player), lambda state:
state.has("The Crypts (E1M7) - Green key", player, 1))
set_rule(world.get_entrance("The Crypts (E1M7) Yellow -> The Crypts (E1M7) Blue", player), lambda state:
state.has("The Crypts (E1M7) - Blue key", player, 1))
set_rule(world.get_entrance("The Crypts (E1M7) Green -> The Crypts (E1M7) Main", player), lambda state:
state.has("The Crypts (E1M7) - Green key", player, 1))
# Hell's Maw (E1M8)
set_rule(world.get_entrance("Hub -> Hell's Maw (E1M8) Main", player), lambda state:
state.has("Hell's Maw (E1M8)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1))
# The Graveyard (E1M9)
set_rule(world.get_entrance("Hub -> The Graveyard (E1M9) Main", player), lambda state:
state.has("The Graveyard (E1M9)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1))
set_rule(world.get_entrance("The Graveyard (E1M9) Main -> The Graveyard (E1M9) Yellow", player), lambda state:
state.has("The Graveyard (E1M9) - Yellow key", player, 1))
set_rule(world.get_entrance("The Graveyard (E1M9) Main -> The Graveyard (E1M9) Green", player), lambda state:
state.has("The Graveyard (E1M9) - Green key", player, 1))
set_rule(world.get_entrance("The Graveyard (E1M9) Main -> The Graveyard (E1M9) Blue", player), lambda state:
state.has("The Graveyard (E1M9) - Blue key", player, 1))
set_rule(world.get_entrance("The Graveyard (E1M9) Yellow -> The Graveyard (E1M9) Main", player), lambda state:
state.has("The Graveyard (E1M9) - Yellow key", player, 1))
set_rule(world.get_entrance("The Graveyard (E1M9) Green -> The Graveyard (E1M9) Main", player), lambda state:
state.has("The Graveyard (E1M9) - Green key", player, 1))
def set_episode2_rules(player, world, pro):
# The Crater (E2M1)
set_rule(world.get_entrance("Hub -> The Crater (E2M1) Main", player), lambda state:
state.has("The Crater (E2M1)", player, 1))
set_rule(world.get_entrance("The Crater (E2M1) Main -> The Crater (E2M1) Yellow", player), lambda state:
state.has("The Crater (E2M1) - Yellow key", player, 1))
set_rule(world.get_entrance("The Crater (E2M1) Yellow -> The Crater (E2M1) Green", player), lambda state:
state.has("The Crater (E2M1) - Green key", player, 1))
set_rule(world.get_entrance("The Crater (E2M1) Green -> The Crater (E2M1) Yellow", player), lambda state:
state.has("The Crater (E2M1) - Green key", player, 1))
# The Lava Pits (E2M2)
set_rule(world.get_entrance("Hub -> The Lava Pits (E2M2) Main", player), lambda state:
(state.has("The Lava Pits (E2M2)", player, 1)) and
(state.has("Ethereal Crossbow", player, 1) or
state.has("Dragon Claw", player, 1)))
set_rule(world.get_entrance("The Lava Pits (E2M2) Main -> The Lava Pits (E2M2) Yellow", player), lambda state:
state.has("The Lava Pits (E2M2) - Yellow key", player, 1))
set_rule(world.get_entrance("The Lava Pits (E2M2) Yellow -> The Lava Pits (E2M2) Green", player), lambda state:
state.has("The Lava Pits (E2M2) - Green key", player, 1))
set_rule(world.get_entrance("The Lava Pits (E2M2) Yellow -> The Lava Pits (E2M2) Main", player), lambda state:
state.has("The Lava Pits (E2M2) - Yellow key", player, 1))
set_rule(world.get_entrance("The Lava Pits (E2M2) Green -> The Lava Pits (E2M2) Yellow", player), lambda state:
state.has("The Lava Pits (E2M2) - Green key", player, 1))
# The River of Fire (E2M3)
set_rule(world.get_entrance("Hub -> The River of Fire (E2M3) Main", player), lambda state:
state.has("The River of Fire (E2M3)", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Ethereal Crossbow", player, 1))
set_rule(world.get_entrance("The River of Fire (E2M3) Main -> The River of Fire (E2M3) Yellow", player), lambda state:
state.has("The River of Fire (E2M3) - Yellow key", player, 1))
set_rule(world.get_entrance("The River of Fire (E2M3) Main -> The River of Fire (E2M3) Blue", player), lambda state:
state.has("The River of Fire (E2M3) - Blue key", player, 1))
set_rule(world.get_entrance("The River of Fire (E2M3) Main -> The River of Fire (E2M3) Green", player), lambda state:
state.has("The River of Fire (E2M3) - Green key", player, 1))
set_rule(world.get_entrance("The River of Fire (E2M3) Blue -> The River of Fire (E2M3) Main", player), lambda state:
state.has("The River of Fire (E2M3) - Blue key", player, 1))
set_rule(world.get_entrance("The River of Fire (E2M3) Yellow -> The River of Fire (E2M3) Main", player), lambda state:
state.has("The River of Fire (E2M3) - Yellow key", player, 1))
set_rule(world.get_entrance("The River of Fire (E2M3) Green -> The River of Fire (E2M3) Main", player), lambda state:
state.has("The River of Fire (E2M3) - Green key", player, 1))
# The Ice Grotto (E2M4)
set_rule(world.get_entrance("Hub -> The Ice Grotto (E2M4) Main", player), lambda state:
(state.has("The Ice Grotto (E2M4)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1)) and
(state.has("Hellstaff", player, 1) or
state.has("Firemace", player, 1)))
set_rule(world.get_entrance("The Ice Grotto (E2M4) Main -> The Ice Grotto (E2M4) Green", player), lambda state:
state.has("The Ice Grotto (E2M4) - Green key", player, 1))
set_rule(world.get_entrance("The Ice Grotto (E2M4) Main -> The Ice Grotto (E2M4) Yellow", player), lambda state:
state.has("The Ice Grotto (E2M4) - Yellow key", player, 1))
set_rule(world.get_entrance("The Ice Grotto (E2M4) Blue -> The Ice Grotto (E2M4) Green", player), lambda state:
state.has("The Ice Grotto (E2M4) - Blue key", player, 1))
set_rule(world.get_entrance("The Ice Grotto (E2M4) Yellow -> The Ice Grotto (E2M4) Magenta", player), lambda state:
state.has("The Ice Grotto (E2M4) - Green key", player, 1) and
state.has("The Ice Grotto (E2M4) - Blue key", player, 1))
set_rule(world.get_entrance("The Ice Grotto (E2M4) Green -> The Ice Grotto (E2M4) Blue", player), lambda state:
state.has("The Ice Grotto (E2M4) - Blue key", player, 1))
# The Catacombs (E2M5)
set_rule(world.get_entrance("Hub -> The Catacombs (E2M5) Main", player), lambda state:
(state.has("The Catacombs (E2M5)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Firemace", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("The Catacombs (E2M5) Main -> The Catacombs (E2M5) Yellow", player), lambda state:
state.has("The Catacombs (E2M5) - Yellow key", player, 1))
set_rule(world.get_entrance("The Catacombs (E2M5) Blue -> The Catacombs (E2M5) Green", player), lambda state:
state.has("The Catacombs (E2M5) - Blue key", player, 1))
set_rule(world.get_entrance("The Catacombs (E2M5) Yellow -> The Catacombs (E2M5) Green", player), lambda state:
state.has("The Catacombs (E2M5) - Yellow key", player, 1))
set_rule(world.get_entrance("The Catacombs (E2M5) Green -> The Catacombs (E2M5) Blue", player), lambda state:
state.has("The Catacombs (E2M5) - Blue key", player, 1))
# The Labyrinth (E2M6)
set_rule(world.get_entrance("Hub -> The Labyrinth (E2M6) Main", player), lambda state:
(state.has("The Labyrinth (E2M6)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Firemace", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("The Labyrinth (E2M6) Main -> The Labyrinth (E2M6) Blue", player), lambda state:
state.has("The Labyrinth (E2M6) - Blue key", player, 1))
set_rule(world.get_entrance("The Labyrinth (E2M6) Main -> The Labyrinth (E2M6) Yellow", player), lambda state:
state.has("The Labyrinth (E2M6) - Yellow key", player, 1))
set_rule(world.get_entrance("The Labyrinth (E2M6) Main -> The Labyrinth (E2M6) Green", player), lambda state:
state.has("The Labyrinth (E2M6) - Green key", player, 1))
set_rule(world.get_entrance("The Labyrinth (E2M6) Blue -> The Labyrinth (E2M6) Main", player), lambda state:
state.has("The Labyrinth (E2M6) - Blue key", player, 1))
# The Great Hall (E2M7)
set_rule(world.get_entrance("Hub -> The Great Hall (E2M7) Main", player), lambda state:
(state.has("The Great Hall (E2M7)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Firemace", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("The Great Hall (E2M7) Main -> The Great Hall (E2M7) Yellow", player), lambda state:
state.has("The Great Hall (E2M7) - Yellow key", player, 1))
set_rule(world.get_entrance("The Great Hall (E2M7) Main -> The Great Hall (E2M7) Green", player), lambda state:
state.has("The Great Hall (E2M7) - Green key", player, 1))
set_rule(world.get_entrance("The Great Hall (E2M7) Blue -> The Great Hall (E2M7) Yellow", player), lambda state:
state.has("The Great Hall (E2M7) - Blue key", player, 1))
set_rule(world.get_entrance("The Great Hall (E2M7) Yellow -> The Great Hall (E2M7) Blue", player), lambda state:
state.has("The Great Hall (E2M7) - Blue key", player, 1))
set_rule(world.get_entrance("The Great Hall (E2M7) Yellow -> The Great Hall (E2M7) Main", player), lambda state:
state.has("The Great Hall (E2M7) - Yellow key", player, 1))
# The Portals of Chaos (E2M8)
set_rule(world.get_entrance("Hub -> The Portals of Chaos (E2M8) Main", player), lambda state:
state.has("The Portals of Chaos (E2M8)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Phoenix Rod", player, 1) and
state.has("Firemace", player, 1) and
state.has("Hellstaff", player, 1))
# The Glacier (E2M9)
set_rule(world.get_entrance("Hub -> The Glacier (E2M9) Main", player), lambda state:
(state.has("The Glacier (E2M9)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Firemace", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("The Glacier (E2M9) Main -> The Glacier (E2M9) Yellow", player), lambda state:
state.has("The Glacier (E2M9) - Yellow key", player, 1))
set_rule(world.get_entrance("The Glacier (E2M9) Main -> The Glacier (E2M9) Blue", player), lambda state:
state.has("The Glacier (E2M9) - Blue key", player, 1))
set_rule(world.get_entrance("The Glacier (E2M9) Main -> The Glacier (E2M9) Green", player), lambda state:
state.has("The Glacier (E2M9) - Green key", player, 1))
set_rule(world.get_entrance("The Glacier (E2M9) Blue -> The Glacier (E2M9) Main", player), lambda state:
state.has("The Glacier (E2M9) - Blue key", player, 1))
set_rule(world.get_entrance("The Glacier (E2M9) Yellow -> The Glacier (E2M9) Main", player), lambda state:
state.has("The Glacier (E2M9) - Yellow key", player, 1))
def set_episode3_rules(player, world, pro):
# The Storehouse (E3M1)
set_rule(world.get_entrance("Hub -> The Storehouse (E3M1) Main", player), lambda state:
state.has("The Storehouse (E3M1)", player, 1))
set_rule(world.get_entrance("The Storehouse (E3M1) Main -> The Storehouse (E3M1) Yellow", player), lambda state:
state.has("The Storehouse (E3M1) - Yellow key", player, 1))
set_rule(world.get_entrance("The Storehouse (E3M1) Main -> The Storehouse (E3M1) Green", player), lambda state:
state.has("The Storehouse (E3M1) - Green key", player, 1))
set_rule(world.get_entrance("The Storehouse (E3M1) Yellow -> The Storehouse (E3M1) Main", player), lambda state:
state.has("The Storehouse (E3M1) - Yellow key", player, 1))
set_rule(world.get_entrance("The Storehouse (E3M1) Green -> The Storehouse (E3M1) Main", player), lambda state:
state.has("The Storehouse (E3M1) - Green key", player, 1))
# The Cesspool (E3M2)
set_rule(world.get_entrance("Hub -> The Cesspool (E3M2) Main", player), lambda state:
state.has("The Cesspool (E3M2)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Firemace", player, 1) and
state.has("Hellstaff", player, 1))
set_rule(world.get_entrance("The Cesspool (E3M2) Main -> The Cesspool (E3M2) Yellow", player), lambda state:
state.has("The Cesspool (E3M2) - Yellow key", player, 1))
set_rule(world.get_entrance("The Cesspool (E3M2) Blue -> The Cesspool (E3M2) Green", player), lambda state:
state.has("The Cesspool (E3M2) - Blue key", player, 1))
set_rule(world.get_entrance("The Cesspool (E3M2) Yellow -> The Cesspool (E3M2) Green", player), lambda state:
state.has("The Cesspool (E3M2) - Green key", player, 1))
set_rule(world.get_entrance("The Cesspool (E3M2) Green -> The Cesspool (E3M2) Blue", player), lambda state:
state.has("The Cesspool (E3M2) - Blue key", player, 1))
set_rule(world.get_entrance("The Cesspool (E3M2) Green -> The Cesspool (E3M2) Yellow", player), lambda state:
state.has("The Cesspool (E3M2) - Green key", player, 1))
# The Confluence (E3M3)
set_rule(world.get_entrance("Hub -> The Confluence (E3M3) Main", player), lambda state:
(state.has("The Confluence (E3M3)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1)) and
(state.has("Gauntlets of the Necromancer", player, 1) or
state.has("Phoenix Rod", player, 1) or
state.has("Firemace", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("The Confluence (E3M3) Main -> The Confluence (E3M3) Green", player), lambda state:
state.has("The Confluence (E3M3) - Green key", player, 1))
set_rule(world.get_entrance("The Confluence (E3M3) Main -> The Confluence (E3M3) Yellow", player), lambda state:
state.has("The Confluence (E3M3) - Yellow key", player, 1))
set_rule(world.get_entrance("The Confluence (E3M3) Blue -> The Confluence (E3M3) Green", player), lambda state:
state.has("The Confluence (E3M3) - Blue key", player, 1))
set_rule(world.get_entrance("The Confluence (E3M3) Green -> The Confluence (E3M3) Main", player), lambda state:
state.has("The Confluence (E3M3) - Green key", player, 1))
set_rule(world.get_entrance("The Confluence (E3M3) Green -> The Confluence (E3M3) Blue", player), lambda state:
state.has("The Confluence (E3M3) - Blue key", player, 1))
# The Azure Fortress (E3M4)
set_rule(world.get_entrance("Hub -> The Azure Fortress (E3M4) Main", player), lambda state:
(state.has("The Azure Fortress (E3M4)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Hellstaff", player, 1)) and
(state.has("Firemace", player, 1) or
state.has("Phoenix Rod", player, 1) or
state.has("Gauntlets of the Necromancer", player, 1)))
set_rule(world.get_entrance("The Azure Fortress (E3M4) Main -> The Azure Fortress (E3M4) Green", player), lambda state:
state.has("The Azure Fortress (E3M4) - Green key", player, 1))
set_rule(world.get_entrance("The Azure Fortress (E3M4) Main -> The Azure Fortress (E3M4) Yellow", player), lambda state:
state.has("The Azure Fortress (E3M4) - Yellow key", player, 1))
# The Ophidian Lair (E3M5)
set_rule(world.get_entrance("Hub -> The Ophidian Lair (E3M5) Main", player), lambda state:
(state.has("The Ophidian Lair (E3M5)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Hellstaff", player, 1)) and
(state.has("Gauntlets of the Necromancer", player, 1) or
state.has("Phoenix Rod", player, 1) or
state.has("Firemace", player, 1)))
set_rule(world.get_entrance("The Ophidian Lair (E3M5) Main -> The Ophidian Lair (E3M5) Yellow", player), lambda state:
state.has("The Ophidian Lair (E3M5) - Yellow key", player, 1))
set_rule(world.get_entrance("The Ophidian Lair (E3M5) Main -> The Ophidian Lair (E3M5) Green", player), lambda state:
state.has("The Ophidian Lair (E3M5) - Green key", player, 1))
# The Halls of Fear (E3M6)
set_rule(world.get_entrance("Hub -> The Halls of Fear (E3M6) Main", player), lambda state:
(state.has("The Halls of Fear (E3M6)", player, 1) and
state.has("Firemace", player, 1) and
state.has("Hellstaff", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Ethereal Crossbow", player, 1)) and
(state.has("Gauntlets of the Necromancer", player, 1) or
state.has("Phoenix Rod", player, 1)))
set_rule(world.get_entrance("The Halls of Fear (E3M6) Main -> The Halls of Fear (E3M6) Yellow", player), lambda state:
state.has("The Halls of Fear (E3M6) - Yellow key", player, 1))
set_rule(world.get_entrance("The Halls of Fear (E3M6) Blue -> The Halls of Fear (E3M6) Yellow", player), lambda state:
state.has("The Halls of Fear (E3M6) - Blue key", player, 1))
set_rule(world.get_entrance("The Halls of Fear (E3M6) Yellow -> The Halls of Fear (E3M6) Blue", player), lambda state:
state.has("The Halls of Fear (E3M6) - Blue key", player, 1))
set_rule(world.get_entrance("The Halls of Fear (E3M6) Yellow -> The Halls of Fear (E3M6) Green", player), lambda state:
state.has("The Halls of Fear (E3M6) - Green key", player, 1))
# The Chasm (E3M7)
set_rule(world.get_entrance("Hub -> The Chasm (E3M7) Main", player), lambda state:
(state.has("The Chasm (E3M7)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Firemace", player, 1) and
state.has("Hellstaff", player, 1)) and
(state.has("Gauntlets of the Necromancer", player, 1) or
state.has("Phoenix Rod", player, 1)))
set_rule(world.get_entrance("The Chasm (E3M7) Main -> The Chasm (E3M7) Yellow", player), lambda state:
state.has("The Chasm (E3M7) - Yellow key", player, 1))
set_rule(world.get_entrance("The Chasm (E3M7) Yellow -> The Chasm (E3M7) Main", player), lambda state:
state.has("The Chasm (E3M7) - Yellow key", player, 1))
set_rule(world.get_entrance("The Chasm (E3M7) Yellow -> The Chasm (E3M7) Green", player), lambda state:
state.has("The Chasm (E3M7) - Green key", player, 1))
set_rule(world.get_entrance("The Chasm (E3M7) Yellow -> The Chasm (E3M7) Blue", player), lambda state:
state.has("The Chasm (E3M7) - Blue key", player, 1))
set_rule(world.get_entrance("The Chasm (E3M7) Green -> The Chasm (E3M7) Yellow", player), lambda state:
state.has("The Chasm (E3M7) - Green key", player, 1))
# D'Sparil'S Keep (E3M8)
set_rule(world.get_entrance("Hub -> D'Sparil'S Keep (E3M8) Main", player), lambda state:
state.has("D'Sparil'S Keep (E3M8)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Phoenix Rod", player, 1) and
state.has("Firemace", player, 1) and
state.has("Hellstaff", player, 1))
# The Aquifier (E3M9)
set_rule(world.get_entrance("Hub -> The Aquifier (E3M9) Main", player), lambda state:
state.has("The Aquifier (E3M9)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Phoenix Rod", player, 1) and
state.has("Firemace", player, 1) and
state.has("Hellstaff", player, 1))
set_rule(world.get_entrance("The Aquifier (E3M9) Main -> The Aquifier (E3M9) Yellow", player), lambda state:
state.has("The Aquifier (E3M9) - Yellow key", player, 1))
set_rule(world.get_entrance("The Aquifier (E3M9) Yellow -> The Aquifier (E3M9) Green", player), lambda state:
state.has("The Aquifier (E3M9) - Green key", player, 1))
set_rule(world.get_entrance("The Aquifier (E3M9) Yellow -> The Aquifier (E3M9) Main", player), lambda state:
state.has("The Aquifier (E3M9) - Yellow key", player, 1))
set_rule(world.get_entrance("The Aquifier (E3M9) Green -> The Aquifier (E3M9) Yellow", player), lambda state:
state.has("The Aquifier (E3M9) - Green key", player, 1))
def set_episode4_rules(player, world, pro):
# Catafalque (E4M1)
set_rule(world.get_entrance("Hub -> Catafalque (E4M1) Main", player), lambda state:
state.has("Catafalque (E4M1)", player, 1))
set_rule(world.get_entrance("Catafalque (E4M1) Main -> Catafalque (E4M1) Yellow", player), lambda state:
state.has("Catafalque (E4M1) - Yellow key", player, 1))
set_rule(world.get_entrance("Catafalque (E4M1) Yellow -> Catafalque (E4M1) Green", player), lambda state:
(state.has("Catafalque (E4M1) - Green key", player, 1)) and (state.has("Ethereal Crossbow", player, 1) or
state.has("Dragon Claw", player, 1) or
state.has("Phoenix Rod", player, 1) or
state.has("Firemace", player, 1) or
state.has("Hellstaff", player, 1)))
# Blockhouse (E4M2)
set_rule(world.get_entrance("Hub -> Blockhouse (E4M2) Main", player), lambda state:
state.has("Blockhouse (E4M2)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1))
set_rule(world.get_entrance("Blockhouse (E4M2) Main -> Blockhouse (E4M2) Yellow", player), lambda state:
state.has("Blockhouse (E4M2) - Yellow key", player, 1))
set_rule(world.get_entrance("Blockhouse (E4M2) Main -> Blockhouse (E4M2) Green", player), lambda state:
state.has("Blockhouse (E4M2) - Green key", player, 1))
set_rule(world.get_entrance("Blockhouse (E4M2) Main -> Blockhouse (E4M2) Blue", player), lambda state:
state.has("Blockhouse (E4M2) - Blue key", player, 1))
set_rule(world.get_entrance("Blockhouse (E4M2) Green -> Blockhouse (E4M2) Main", player), lambda state:
state.has("Blockhouse (E4M2) - Green key", player, 1))
set_rule(world.get_entrance("Blockhouse (E4M2) Blue -> Blockhouse (E4M2) Main", player), lambda state:
state.has("Blockhouse (E4M2) - Blue key", player, 1))
# Ambulatory (E4M3)
set_rule(world.get_entrance("Hub -> Ambulatory (E4M3) Main", player), lambda state:
(state.has("Ambulatory (E4M3)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Firemace", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("Ambulatory (E4M3) Main -> Ambulatory (E4M3) Blue", player), lambda state:
state.has("Ambulatory (E4M3) - Blue key", player, 1))
set_rule(world.get_entrance("Ambulatory (E4M3) Main -> Ambulatory (E4M3) Yellow", player), lambda state:
state.has("Ambulatory (E4M3) - Yellow key", player, 1))
set_rule(world.get_entrance("Ambulatory (E4M3) Main -> Ambulatory (E4M3) Green", player), lambda state:
state.has("Ambulatory (E4M3) - Green key", player, 1))
# Sepulcher (E4M4)
set_rule(world.get_entrance("Hub -> Sepulcher (E4M4) Main", player), lambda state:
(state.has("Sepulcher (E4M4)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Firemace", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Hellstaff", player, 1)))
# Great Stair (E4M5)
set_rule(world.get_entrance("Hub -> Great Stair (E4M5) Main", player), lambda state:
(state.has("Great Stair (E4M5)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Firemace", player, 1)) and
(state.has("Hellstaff", player, 1) or
state.has("Phoenix Rod", player, 1)))
set_rule(world.get_entrance("Great Stair (E4M5) Main -> Great Stair (E4M5) Yellow", player), lambda state:
state.has("Great Stair (E4M5) - Yellow key", player, 1))
set_rule(world.get_entrance("Great Stair (E4M5) Blue -> Great Stair (E4M5) Green", player), lambda state:
state.has("Great Stair (E4M5) - Blue key", player, 1))
set_rule(world.get_entrance("Great Stair (E4M5) Yellow -> Great Stair (E4M5) Green", player), lambda state:
state.has("Great Stair (E4M5) - Green key", player, 1))
set_rule(world.get_entrance("Great Stair (E4M5) Green -> Great Stair (E4M5) Blue", player), lambda state:
state.has("Great Stair (E4M5) - Blue key", player, 1))
set_rule(world.get_entrance("Great Stair (E4M5) Green -> Great Stair (E4M5) Yellow", player), lambda state:
state.has("Great Stair (E4M5) - Green key", player, 1))
# Halls of the Apostate (E4M6)
set_rule(world.get_entrance("Hub -> Halls of the Apostate (E4M6) Main", player), lambda state:
(state.has("Halls of the Apostate (E4M6)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Firemace", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("Halls of the Apostate (E4M6) Main -> Halls of the Apostate (E4M6) Yellow", player), lambda state:
state.has("Halls of the Apostate (E4M6) - Yellow key", player, 1))
set_rule(world.get_entrance("Halls of the Apostate (E4M6) Blue -> Halls of the Apostate (E4M6) Green", player), lambda state:
state.has("Halls of the Apostate (E4M6) - Blue key", player, 1))
set_rule(world.get_entrance("Halls of the Apostate (E4M6) Yellow -> Halls of the Apostate (E4M6) Green", player), lambda state:
state.has("Halls of the Apostate (E4M6) - Green key", player, 1))
set_rule(world.get_entrance("Halls of the Apostate (E4M6) Green -> Halls of the Apostate (E4M6) Yellow", player), lambda state:
state.has("Halls of the Apostate (E4M6) - Green key", player, 1))
set_rule(world.get_entrance("Halls of the Apostate (E4M6) Green -> Halls of the Apostate (E4M6) Blue", player), lambda state:
state.has("Halls of the Apostate (E4M6) - Blue key", player, 1))
# Ramparts of Perdition (E4M7)
set_rule(world.get_entrance("Hub -> Ramparts of Perdition (E4M7) Main", player), lambda state:
(state.has("Ramparts of Perdition (E4M7)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Firemace", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("Ramparts of Perdition (E4M7) Main -> Ramparts of Perdition (E4M7) Yellow", player), lambda state:
state.has("Ramparts of Perdition (E4M7) - Yellow key", player, 1))
set_rule(world.get_entrance("Ramparts of Perdition (E4M7) Blue -> Ramparts of Perdition (E4M7) Yellow", player), lambda state:
state.has("Ramparts of Perdition (E4M7) - Blue key", player, 1))
set_rule(world.get_entrance("Ramparts of Perdition (E4M7) Yellow -> Ramparts of Perdition (E4M7) Main", player), lambda state:
state.has("Ramparts of Perdition (E4M7) - Yellow key", player, 1))
set_rule(world.get_entrance("Ramparts of Perdition (E4M7) Yellow -> Ramparts of Perdition (E4M7) Green", player), lambda state:
state.has("Ramparts of Perdition (E4M7) - Green key", player, 1))
set_rule(world.get_entrance("Ramparts of Perdition (E4M7) Yellow -> Ramparts of Perdition (E4M7) Blue", player), lambda state:
state.has("Ramparts of Perdition (E4M7) - Blue key", player, 1))
set_rule(world.get_entrance("Ramparts of Perdition (E4M7) Green -> Ramparts of Perdition (E4M7) Yellow", player), lambda state:
state.has("Ramparts of Perdition (E4M7) - Green key", player, 1))
# Shattered Bridge (E4M8)
set_rule(world.get_entrance("Hub -> Shattered Bridge (E4M8) Main", player), lambda state:
state.has("Shattered Bridge (E4M8)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Phoenix Rod", player, 1) and
state.has("Firemace", player, 1) and
state.has("Hellstaff", player, 1))
set_rule(world.get_entrance("Shattered Bridge (E4M8) Main -> Shattered Bridge (E4M8) Yellow", player), lambda state:
state.has("Shattered Bridge (E4M8) - Yellow key", player, 1))
set_rule(world.get_entrance("Shattered Bridge (E4M8) Yellow -> Shattered Bridge (E4M8) Main", player), lambda state:
state.has("Shattered Bridge (E4M8) - Yellow key", player, 1))
# Mausoleum (E4M9)
set_rule(world.get_entrance("Hub -> Mausoleum (E4M9) Main", player), lambda state:
(state.has("Mausoleum (E4M9)", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Firemace", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("Mausoleum (E4M9) Main -> Mausoleum (E4M9) Yellow", player), lambda state:
state.has("Mausoleum (E4M9) - Yellow key", player, 1))
set_rule(world.get_entrance("Mausoleum (E4M9) Yellow -> Mausoleum (E4M9) Main", player), lambda state:
state.has("Mausoleum (E4M9) - Yellow key", player, 1))
def set_episode5_rules(player, world, pro):
# Ochre Cliffs (E5M1)
set_rule(world.get_entrance("Hub -> Ochre Cliffs (E5M1) Main", player), lambda state:
state.has("Ochre Cliffs (E5M1)", player, 1))
set_rule(world.get_entrance("Ochre Cliffs (E5M1) Main -> Ochre Cliffs (E5M1) Yellow", player), lambda state:
state.has("Ochre Cliffs (E5M1) - Yellow key", player, 1))
set_rule(world.get_entrance("Ochre Cliffs (E5M1) Blue -> Ochre Cliffs (E5M1) Yellow", player), lambda state:
state.has("Ochre Cliffs (E5M1) - Blue key", player, 1))
set_rule(world.get_entrance("Ochre Cliffs (E5M1) Yellow -> Ochre Cliffs (E5M1) Main", player), lambda state:
state.has("Ochre Cliffs (E5M1) - Yellow key", player, 1))
set_rule(world.get_entrance("Ochre Cliffs (E5M1) Yellow -> Ochre Cliffs (E5M1) Green", player), lambda state:
state.has("Ochre Cliffs (E5M1) - Green key", player, 1))
set_rule(world.get_entrance("Ochre Cliffs (E5M1) Yellow -> Ochre Cliffs (E5M1) Blue", player), lambda state:
state.has("Ochre Cliffs (E5M1) - Blue key", player, 1))
set_rule(world.get_entrance("Ochre Cliffs (E5M1) Green -> Ochre Cliffs (E5M1) Yellow", player), lambda state:
state.has("Ochre Cliffs (E5M1) - Green key", player, 1))
# Rapids (E5M2)
set_rule(world.get_entrance("Hub -> Rapids (E5M2) Main", player), lambda state:
state.has("Rapids (E5M2)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1))
set_rule(world.get_entrance("Rapids (E5M2) Main -> Rapids (E5M2) Yellow", player), lambda state:
state.has("Rapids (E5M2) - Yellow key", player, 1))
set_rule(world.get_entrance("Rapids (E5M2) Yellow -> Rapids (E5M2) Main", player), lambda state:
state.has("Rapids (E5M2) - Yellow key", player, 1))
set_rule(world.get_entrance("Rapids (E5M2) Yellow -> Rapids (E5M2) Green", player), lambda state:
state.has("Rapids (E5M2) - Green key", player, 1))
# Quay (E5M3)
set_rule(world.get_entrance("Hub -> Quay (E5M3) Main", player), lambda state:
(state.has("Quay (E5M3)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Hellstaff", player, 1) or
state.has("Firemace", player, 1)))
set_rule(world.get_entrance("Quay (E5M3) Main -> Quay (E5M3) Yellow", player), lambda state:
state.has("Quay (E5M3) - Yellow key", player, 1))
set_rule(world.get_entrance("Quay (E5M3) Main -> Quay (E5M3) Green", player), lambda state:
state.has("Quay (E5M3) - Green key", player, 1))
set_rule(world.get_entrance("Quay (E5M3) Main -> Quay (E5M3) Blue", player), lambda state:
state.has("Quay (E5M3) - Blue key", player, 1))
set_rule(world.get_entrance("Quay (E5M3) Blue -> Quay (E5M3) Green", player), lambda state:
state.has("Quay (E5M3) - Blue key", player, 1))
set_rule(world.get_entrance("Quay (E5M3) Yellow -> Quay (E5M3) Main", player), lambda state:
state.has("Quay (E5M3) - Yellow key", player, 1))
set_rule(world.get_entrance("Quay (E5M3) Green -> Quay (E5M3) Main", player), lambda state:
state.has("Quay (E5M3) - Green key", player, 1))
set_rule(world.get_entrance("Quay (E5M3) Green -> Quay (E5M3) Blue", player), lambda state:
state.has("Quay (E5M3) - Blue key", player, 1))
# Courtyard (E5M4)
set_rule(world.get_entrance("Hub -> Courtyard (E5M4) Main", player), lambda state:
(state.has("Courtyard (E5M4)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Firemace", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("Courtyard (E5M4) Main -> Courtyard (E5M4) Kakis", player), lambda state:
state.has("Courtyard (E5M4) - Yellow key", player, 1) or
state.has("Courtyard (E5M4) - Green key", player, 1))
set_rule(world.get_entrance("Courtyard (E5M4) Main -> Courtyard (E5M4) Blue", player), lambda state:
state.has("Courtyard (E5M4) - Blue key", player, 1))
set_rule(world.get_entrance("Courtyard (E5M4) Blue -> Courtyard (E5M4) Main", player), lambda state:
state.has("Courtyard (E5M4) - Blue key", player, 1))
set_rule(world.get_entrance("Courtyard (E5M4) Kakis -> Courtyard (E5M4) Main", player), lambda state:
state.has("Courtyard (E5M4) - Yellow key", player, 1) or
state.has("Courtyard (E5M4) - Green key", player, 1))
# Hydratyr (E5M5)
set_rule(world.get_entrance("Hub -> Hydratyr (E5M5) Main", player), lambda state:
(state.has("Hydratyr (E5M5)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Firemace", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("Hydratyr (E5M5) Main -> Hydratyr (E5M5) Yellow", player), lambda state:
state.has("Hydratyr (E5M5) - Yellow key", player, 1))
set_rule(world.get_entrance("Hydratyr (E5M5) Blue -> Hydratyr (E5M5) Green", player), lambda state:
state.has("Hydratyr (E5M5) - Blue key", player, 1))
set_rule(world.get_entrance("Hydratyr (E5M5) Yellow -> Hydratyr (E5M5) Green", player), lambda state:
state.has("Hydratyr (E5M5) - Green key", player, 1))
set_rule(world.get_entrance("Hydratyr (E5M5) Green -> Hydratyr (E5M5) Blue", player), lambda state:
state.has("Hydratyr (E5M5) - Blue key", player, 1))
# Colonnade (E5M6)
set_rule(world.get_entrance("Hub -> Colonnade (E5M6) Main", player), lambda state:
(state.has("Colonnade (E5M6)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Firemace", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("Colonnade (E5M6) Main -> Colonnade (E5M6) Yellow", player), lambda state:
state.has("Colonnade (E5M6) - Yellow key", player, 1))
set_rule(world.get_entrance("Colonnade (E5M6) Main -> Colonnade (E5M6) Blue", player), lambda state:
state.has("Colonnade (E5M6) - Blue key", player, 1))
set_rule(world.get_entrance("Colonnade (E5M6) Blue -> Colonnade (E5M6) Main", player), lambda state:
state.has("Colonnade (E5M6) - Blue key", player, 1))
set_rule(world.get_entrance("Colonnade (E5M6) Yellow -> Colonnade (E5M6) Green", player), lambda state:
state.has("Colonnade (E5M6) - Green key", player, 1))
set_rule(world.get_entrance("Colonnade (E5M6) Green -> Colonnade (E5M6) Yellow", player), lambda state:
state.has("Colonnade (E5M6) - Green key", player, 1))
# Foetid Manse (E5M7)
set_rule(world.get_entrance("Hub -> Foetid Manse (E5M7) Main", player), lambda state:
(state.has("Foetid Manse (E5M7)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Firemace", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1)) and
(state.has("Phoenix Rod", player, 1) or
state.has("Hellstaff", player, 1)))
set_rule(world.get_entrance("Foetid Manse (E5M7) Main -> Foetid Manse (E5M7) Yellow", player), lambda state:
state.has("Foetid Manse (E5M7) - Yellow key", player, 1))
set_rule(world.get_entrance("Foetid Manse (E5M7) Yellow -> Foetid Manse (E5M7) Green", player), lambda state:
state.has("Foetid Manse (E5M7) - Green key", player, 1))
set_rule(world.get_entrance("Foetid Manse (E5M7) Yellow -> Foetid Manse (E5M7) Blue", player), lambda state:
state.has("Foetid Manse (E5M7) - Blue key", player, 1))
# Field of Judgement (E5M8)
set_rule(world.get_entrance("Hub -> Field of Judgement (E5M8) Main", player), lambda state:
state.has("Field of Judgement (E5M8)", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Phoenix Rod", player, 1) and
state.has("Firemace", player, 1) and
state.has("Hellstaff", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Bag of Holding", player, 1))
# Skein of D'Sparil (E5M9)
set_rule(world.get_entrance("Hub -> Skein of D'Sparil (E5M9) Main", player), lambda state:
state.has("Skein of D'Sparil (E5M9)", player, 1) and
state.has("Bag of Holding", player, 1) and
state.has("Hellstaff", player, 1) and
state.has("Phoenix Rod", player, 1) and
state.has("Dragon Claw", player, 1) and
state.has("Ethereal Crossbow", player, 1) and
state.has("Gauntlets of the Necromancer", player, 1) and
state.has("Firemace", player, 1))
set_rule(world.get_entrance("Skein of D'Sparil (E5M9) Main -> Skein of D'Sparil (E5M9) Blue", player), lambda state:
state.has("Skein of D'Sparil (E5M9) - Blue key", player, 1))
set_rule(world.get_entrance("Skein of D'Sparil (E5M9) Main -> Skein of D'Sparil (E5M9) Yellow", player), lambda state:
state.has("Skein of D'Sparil (E5M9) - Yellow key", player, 1))
set_rule(world.get_entrance("Skein of D'Sparil (E5M9) Main -> Skein of D'Sparil (E5M9) Green", player), lambda state:
state.has("Skein of D'Sparil (E5M9) - Green key", player, 1))
set_rule(world.get_entrance("Skein of D'Sparil (E5M9) Yellow -> Skein of D'Sparil (E5M9) Main", player), lambda state:
state.has("Skein of D'Sparil (E5M9) - Yellow key", player, 1))
set_rule(world.get_entrance("Skein of D'Sparil (E5M9) Green -> Skein of D'Sparil (E5M9) Main", player), lambda state:
state.has("Skein of D'Sparil (E5M9) - Green key", player, 1))
def set_rules(heretic_world: "HereticWorld", included_episodes, pro):
player = heretic_world.player
world = heretic_world.multiworld
if included_episodes[0]:
set_episode1_rules(player, world, pro)
if included_episodes[1]:
set_episode2_rules(player, world, pro)
if included_episodes[2]:
set_episode3_rules(player, world, pro)
if included_episodes[3]:
set_episode4_rules(player, world, pro)
if included_episodes[4]:
set_episode5_rules(player, world, pro)

287
worlds/heretic/__init__.py Normal file
View File

@ -0,0 +1,287 @@
import functools
import logging
from typing import Any, Dict, List, Set
from BaseClasses import Entrance, CollectionState, Item, ItemClassification, Location, MultiWorld, Region, Tutorial
from worlds.AutoWorld import WebWorld, World
from . import Items, Locations, Maps, Options, Regions, Rules
logger = logging.getLogger("Heretic")
HERETIC_TYPE_LEVEL_COMPLETE = -2
HERETIC_TYPE_MAP_SCROLL = 35
class HereticLocation(Location):
game: str = "Heretic"
class HereticItem(Item):
game: str = "Heretic"
class HereticWeb(WebWorld):
tutorials = [Tutorial(
"Multiworld Setup Guide",
"A guide to setting up the Heretic randomizer connected to an Archipelago Multiworld",
"English",
"setup_en.md",
"setup/en",
["Daivuk"]
)]
theme = "dirt"
class HereticWorld(World):
"""
Heretic is a dark fantasy first-person shooter video game released in December 1994. It was developed by Raven Software.
"""
option_definitions = Options.options
game = "Heretic"
web = HereticWeb()
data_version = 3
required_client_version = (0, 3, 9)
item_name_to_id = {data["name"]: item_id for item_id, data in Items.item_table.items()}
item_name_groups = Items.item_name_groups
location_name_to_id = {data["name"]: loc_id for loc_id, data in Locations.location_table.items()}
location_name_groups = Locations.location_name_groups
starting_level_for_episode: List[str] = [
"The Docks (E1M1)",
"The Crater (E2M1)",
"The Storehouse (E3M1)",
"Catafalque (E4M1)",
"Ochre Cliffs (E5M1)"
]
boss_level_for_espidoes: List[str] = [
"Hell's Maw (E1M8)",
"The Portals of Chaos (E2M8)",
"D'Sparil'S Keep (E3M8)",
"Shattered Bridge (E4M8)",
"Field of Judgement (E5M8)"
]
# Item ratio that scales depending on episode count. These are the ratio for 1 episode.
items_ratio: Dict[str, float] = {
"Timebomb of the Ancients": 16,
"Tome of Power": 16,
"Silver Shield": 10,
"Enchanted Shield": 5,
"Morph Ovum": 3,
"Mystic Urn": 2,
"Chaos Device": 1,
"Ring of Invincibility": 1,
"Shadowsphere": 1
}
def __init__(self, world: MultiWorld, player: int):
self.included_episodes = [1, 1, 1, 0, 0]
self.location_count = 0
super().__init__(world, player)
def get_episode_count(self):
return functools.reduce(lambda count, episode: count + episode, self.included_episodes)
def generate_early(self):
# Cache which episodes are included
for i in range(5):
self.included_episodes[i] = getattr(self.multiworld, f"episode{i + 1}")[self.player].value
# If no episodes selected, select Episode 1
if self.get_episode_count() == 0:
self.included_episodes[0] = 1
def create_regions(self):
pro = getattr(self.multiworld, "pro")[self.player].value
check_sanity = getattr(self.multiworld, "check_sanity")[self.player].value
# Main regions
menu_region = Region("Menu", self.player, self.multiworld)
hub_region = Region("Hub", self.player, self.multiworld)
self.multiworld.regions += [menu_region, hub_region]
menu_region.add_exits(["Hub"])
# Create regions and locations
main_regions = []
connections = []
for region_dict in Regions.regions:
if not self.included_episodes[region_dict["episode"] - 1]:
continue
region_name = region_dict["name"]
if region_dict["connects_to_hub"]:
main_regions.append(region_name)
region = Region(region_name, self.player, self.multiworld)
region.add_locations({
loc["name"]: loc_id
for loc_id, loc in Locations.location_table.items()
if loc["region"] == region_name and (not loc["check_sanity"] or check_sanity)
}, HereticLocation)
self.multiworld.regions.append(region)
for connection_dict in region_dict["connections"]:
# Check if it's a pro-only connection
if connection_dict["pro"] and not pro:
continue
connections.append((region, connection_dict["target"]))
# Connect main regions to Hub
hub_region.add_exits(main_regions)
# Do the other connections between regions (They are not all both ways)
for connection in connections:
source = connection[0]
target = self.multiworld.get_region(connection[1], self.player)
entrance = Entrance(self.player, f"{source.name} -> {target.name}", source)
source.exits.append(entrance)
entrance.connect(target)
# Sum locations for items creation
self.location_count = len(self.multiworld.get_locations(self.player))
def completion_rule(self, state: CollectionState):
goal_levels = Maps.map_names
if getattr(self.multiworld, "goal")[self.player].value:
goal_levels = self.boss_level_for_espidoes
for map_name in goal_levels:
if map_name + " - Exit" not in self.location_name_to_id:
continue
# Exit location names are in form: The Docks (E1M1) - Exit
loc = Locations.location_table[self.location_name_to_id[map_name + " - Exit"]]
if not self.included_episodes[loc["episode"] - 1]:
continue
# Map complete item names are in form: The Docks (E1M1) - Complete
if not state.has(map_name + " - Complete", self.player, 1):
return False
return True
def set_rules(self):
pro = getattr(self.multiworld, "pro")[self.player].value
allow_death_logic = getattr(self.multiworld, "allow_death_logic")[self.player].value
Rules.set_rules(self, self.included_episodes, pro)
self.multiworld.completion_condition[self.player] = lambda state: self.completion_rule(state)
# Forbid progression items to locations that can be missed and can't be picked up. (e.g. One-time timed
# platform) Unless the user allows for it.
if not allow_death_logic:
for death_logic_location in Locations.death_logic_locations:
self.multiworld.exclude_locations[self.player].value.add(death_logic_location)
def create_item(self, name: str) -> HereticItem:
item_id: int = self.item_name_to_id[name]
return HereticItem(name, Items.item_table[item_id]["classification"], item_id, self.player)
def create_items(self):
itempool: List[HereticItem] = []
start_with_map_scrolls: bool = getattr(self.multiworld, "start_with_map_scrolls")[self.player].value
# Items
for item_id, item in Items.item_table.items():
if item["doom_type"] == HERETIC_TYPE_LEVEL_COMPLETE:
continue # We'll fill it manually later
if item["doom_type"] == HERETIC_TYPE_MAP_SCROLL and start_with_map_scrolls:
continue # We'll fill it manually, and we will put fillers in place
if item["episode"] != -1 and not self.included_episodes[item["episode"] - 1]:
continue
count = item["count"] if item["name"] not in self.starting_level_for_episode else item["count"] - 1
itempool += [self.create_item(item["name"]) for _ in range(count)]
# Place end level items in locked locations
for map_name in Maps.map_names:
loc_name = map_name + " - Exit"
item_name = map_name + " - Complete"
if loc_name not in self.location_name_to_id:
continue
if item_name not in self.item_name_to_id:
continue
loc = Locations.location_table[self.location_name_to_id[loc_name]]
if not self.included_episodes[loc["episode"] - 1]:
continue
self.multiworld.get_location(loc_name, self.player).place_locked_item(self.create_item(item_name))
self.location_count -= 1
# Give starting levels right away
for i in range(len(self.included_episodes)):
if self.included_episodes[i]:
self.multiworld.push_precollected(self.create_item(self.starting_level_for_episode[i]))
# Give Computer area maps if option selected
if getattr(self.multiworld, "start_with_map_scrolls")[self.player].value:
for item_id, item_dict in Items.item_table.items():
item_episode = item_dict["episode"]
if item_episode > 0:
if item_dict["doom_type"] == HERETIC_TYPE_MAP_SCROLL and self.included_episodes[item_episode - 1]:
self.multiworld.push_precollected(self.create_item(item_dict["name"]))
# Fill the rest starting with powerups, then fillers
self.create_ratioed_items("Chaos Device", itempool)
self.create_ratioed_items("Morph Ovum", itempool)
self.create_ratioed_items("Mystic Urn", itempool)
self.create_ratioed_items("Ring of Invincibility", itempool)
self.create_ratioed_items("Shadowsphere", itempool)
self.create_ratioed_items("Timebomb of the Ancients", itempool)
self.create_ratioed_items("Tome of Power", itempool)
self.create_ratioed_items("Silver Shield", itempool)
self.create_ratioed_items("Enchanted Shield", itempool)
while len(itempool) < self.location_count:
itempool.append(self.create_item(self.get_filler_item_name()))
# add itempool to multiworld
self.multiworld.itempool += itempool
def get_filler_item_name(self):
return self.multiworld.random.choice([
"Quartz Flask",
"Crystal Geode",
"Energy Orb",
"Greater Runes",
"Inferno Orb",
"Pile of Mace Spheres",
"Quiver of Ethereal Arrows"
])
def create_ratioed_items(self, item_name: str, itempool: List[HereticItem]):
remaining_loc = self.location_count - len(itempool)
if remaining_loc <= 0:
return
episode_count = self.get_episode_count()
count = min(remaining_loc, max(1, self.items_ratio[item_name] * episode_count))
if count == 0:
logger.warning("Warning, no " + item_name + " will be placed.")
return
for i in range(count):
itempool.append(self.create_item(item_name))
def fill_slot_data(self) -> Dict[str, Any]:
slot_data = self.options.as_dict("difficulty", "random_monsters", "random_pickups", "random_music", "allow_death_logic", "pro", "death_link", "reset_level_on_death", "check_sanity")
# Make sure we send proper episode settings
slot_data["episode1"] = self.included_episodes[0]
slot_data["episode2"] = self.included_episodes[1]
slot_data["episode3"] = self.included_episodes[2]
slot_data["episode4"] = self.included_episodes[3]
slot_data["episode5"] = self.included_episodes[4]
return slot_data

View File

@ -0,0 +1,23 @@
# Heretic
## Where is the settings page?
The [player settings page](../player-settings) contains the options needed to configure your game session.
## What does randomization do to this game?
Weapons, keys, and level unlocks have been randomized. Monsters and Pickups are also randomized. Typically, you will end up playing different levels out of order to find your keys and level unlocks and eventually complete your game.
Maps can be selected on a level select screen. You can exit a level at any time by visiting the hub station at the beginning of each level. The state of each level is saved and restored upon re-entering the level.
## What is the goal?
The goal is to complete every level in the episodes you have chosen to play.
## What is a "check" in The Heretic?
Weapons, keys, and powerups have been replaced with Archipelago checks. Some have been selectively removed because Heretic contains a lot of collectibles. Usually when many bunch together, one was kept. The switch at the end of each level is also a check.
## What "items" can you unlock in Heretic?
Keys and level unlocks are your main progression items. Weapon unlocks and some upgrades are your useful items. Powerups, ammo, healing, and armor are filler items.

View File

@ -0,0 +1,51 @@
# Heretic Randomizer Setup
## Required Software
- [Heretic (e.g. Steam version)](https://store.steampowered.com/app/2390/Heretic_Shadow_of_the_Serpent_Riders/)
- [Archipelago Crispy DOOM](https://github.com/Daivuk/apdoom/releases) (Same download for DOOM 1993, DOOM II and Heretic)
## Optional Software
- [ArchipelagoTextClient](https://github.com/ArchipelagoMW/Archipelago/releases)
## Installing APDoom
1. Download [APDOOM.zip](https://github.com/Daivuk/apdoom/releases) and extract it.
2. Copy HERETIC.WAD from your steam install into the extracted folder.
You can find the folder in steam by finding the game in your library,
right clicking it and choosing *Manage→Browse Local Files*.
## Joining a MultiWorld Game
1. Launch apdoom-launcher.exe
2. Choose Heretic in the dropdown
3. Enter the Archipelago server address, slot name, and password (if you have one)
4. Press "Launch Game"
5. Enjoy!
To continue a game, follow the same connection steps.
Connecting with a different seed won't erase your progress in other seeds.
## Archipelago Text Client
We recommend having Archipelago's Text Client open on the side to keep track of what items you receive and send.
APDOOM has in-game messages,
but they disappear quickly and there's no reasonable way to check your message history in-game.
### Hinting
To hint from in-game, use the chat (Default key: 'T'). Hinting from Heretic can be difficult because names are rather long and contain special characters. For example:
```
!hint The River of Fire (E2M3) - Green key
```
The game has a hint helper implemented, where you can simply type this:
```
!hint e2m3 green
```
For this to work, include the map short name (`E1M1`), followed by one of the keywords: `map`, `blue`, `yellow`, `green`.
## Auto-Tracking
APDOOM has a functional map tracker integrated into the level select screen.
It tells you which levels you have unlocked, which keys you have for each level, which levels have been completed,
and how many of the checks you have completed in each level.