DOOM II: implement new game (#2255)

This commit is contained in:
David St-Louis 2023-11-24 12:08:02 -05:00 committed by GitHub
parent 530e792c3c
commit c5b0330223
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 6048 additions and 0 deletions

View File

@ -53,6 +53,8 @@ Currently, the following games are supported:
* Terraria
* Lingo
* Pokémon Emerald
* DOOM II
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

1071
worlds/doom_ii/Items.py Normal file

File diff suppressed because it is too large Load Diff

3442
worlds/doom_ii/Locations.py Normal file

File diff suppressed because it is too large Load Diff

39
worlds/doom_ii/Maps.py Normal file
View File

@ -0,0 +1,39 @@
# This file is auto generated. More info: https://github.com/Daivuk/apdoom
from typing import List
map_names: List[str] = [
'Entryway (MAP01)',
'Underhalls (MAP02)',
'The Gantlet (MAP03)',
'The Focus (MAP04)',
'The Waste Tunnels (MAP05)',
'The Crusher (MAP06)',
'Dead Simple (MAP07)',
'Tricks and Traps (MAP08)',
'The Pit (MAP09)',
'Refueling Base (MAP10)',
'Circle of Death (MAP11)',
'The Factory (MAP12)',
'Downtown (MAP13)',
'The Inmost Dens (MAP14)',
'Industrial Zone (MAP15)',
'Suburbs (MAP16)',
'Tenements (MAP17)',
'The Courtyard (MAP18)',
'The Citadel (MAP19)',
'Gotcha! (MAP20)',
'Nirvana (MAP21)',
'The Catacombs (MAP22)',
'Barrels o Fun (MAP23)',
'The Chasm (MAP24)',
'Bloodfalls (MAP25)',
'The Abandoned Mines (MAP26)',
'Monster Condo (MAP27)',
'The Spirit World (MAP28)',
'The Living End (MAP29)',
'Icon of Sin (MAP30)',
'Wolfenstein2 (MAP31)',
'Grosse2 (MAP32)',
]

150
worlds/doom_ii/Options.py Normal file
View File

@ -0,0 +1,150 @@
import typing
from Options import PerGameCommonOptions, Choice, Toggle, DeathLink, DefaultOnToggle, StartInventoryPool
from dataclasses import dataclass
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.
"""
display_name = "Difficulty"
option_baby = 0
option_easy = 1
option_medium = 2
option_hard = 3
option_nightmare = 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 = 2
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 FlipLevels(Choice):
"""
Flip levels on one axis.
vanilla: No flipping
flipped: All levels are flipped
random: Random levels are flipped
"""
display_name = "Flip Levels"
option_vanilla = 0
option_flipped = 1
option_randomly_flipped = 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 Doom"
class StartWithComputerAreaMaps(Toggle):
"""Give the player all Computer Area Map items from the start."""
display_name = "Start With Computer Area Maps"
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 Episode1(DefaultOnToggle):
"""Subterranean and Outpost.
If none of the episodes are chosen, Episode 1 will be chosen by default."""
display_name = "Episode 1"
class Episode2(DefaultOnToggle):
"""City.
If none of the episodes are chosen, Episode 1 will be chosen by default."""
display_name = "Episode 2"
class Episode3(DefaultOnToggle):
"""Hell.
If none of the episodes are chosen, Episode 1 will be chosen by default."""
display_name = "Episode 3"
class SecretLevels(Toggle):
"""Secret levels.
This is too short to be an episode. It's additive.
Another episode will have to be selected along with this one.
Otherwise episode 1 will be added."""
display_name = "Secret Levels"
@dataclass
class DOOM2Options(PerGameCommonOptions):
start_inventory_from_pool: StartInventoryPool
difficulty: Difficulty
random_monsters: RandomMonsters
random_pickups: RandomPickups
random_music: RandomMusic
flip_levels: FlipLevels
allow_death_logic: AllowDeathLogic
pro: Pro
start_with_computer_area_maps: StartWithComputerAreaMaps
death_link: DeathLink
reset_level_on_death: ResetLevelOnDeath
episode1: Episode1
episode2: Episode2
episode3: Episode3
episode4: SecretLevels

502
worlds/doom_ii/Regions.py Normal file
View File

@ -0,0 +1,502 @@
# 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] = [
# Entryway (MAP01)
{"name":"Entryway (MAP01) Main",
"connects_to_hub":True,
"episode":1,
"connections":[]},
# Underhalls (MAP02)
{"name":"Underhalls (MAP02) Main",
"connects_to_hub":True,
"episode":1,
"connections":[{"target":"Underhalls (MAP02) Red","pro":False}]},
{"name":"Underhalls (MAP02) Blue",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"Underhalls (MAP02) Red","pro":False}]},
{"name":"Underhalls (MAP02) Red",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"Underhalls (MAP02) Blue","pro":False},
{"target":"Underhalls (MAP02) Main","pro":False}]},
# The Gantlet (MAP03)
{"name":"The Gantlet (MAP03) Main",
"connects_to_hub":True,
"episode":1,
"connections":[
{"target":"The Gantlet (MAP03) Blue","pro":False},
{"target":"The Gantlet (MAP03) Blue Pro Jump","pro":True}]},
{"name":"The Gantlet (MAP03) Blue",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Gantlet (MAP03) Main","pro":False},
{"target":"The Gantlet (MAP03) Red","pro":False},
{"target":"The Gantlet (MAP03) Blue Pro Jump","pro":False}]},
{"name":"The Gantlet (MAP03) Red",
"connects_to_hub":False,
"episode":1,
"connections":[]},
{"name":"The Gantlet (MAP03) Blue Pro Jump",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Gantlet (MAP03) Blue","pro":False}]},
# The Focus (MAP04)
{"name":"The Focus (MAP04) Main",
"connects_to_hub":True,
"episode":1,
"connections":[
{"target":"The Focus (MAP04) Red","pro":False},
{"target":"The Focus (MAP04) Blue","pro":False}]},
{"name":"The Focus (MAP04) Blue",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Focus (MAP04) Main","pro":False}]},
{"name":"The Focus (MAP04) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Focus (MAP04) Red","pro":False}]},
{"name":"The Focus (MAP04) Red",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Focus (MAP04) Yellow","pro":False},
{"target":"The Focus (MAP04) Main","pro":False}]},
# The Waste Tunnels (MAP05)
{"name":"The Waste Tunnels (MAP05) Main",
"connects_to_hub":True,
"episode":1,
"connections":[
{"target":"The Waste Tunnels (MAP05) Red","pro":False},
{"target":"The Waste Tunnels (MAP05) Blue","pro":False}]},
{"name":"The Waste Tunnels (MAP05) Blue",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Waste Tunnels (MAP05) Yellow","pro":False},
{"target":"The Waste Tunnels (MAP05) Main","pro":False}]},
{"name":"The Waste Tunnels (MAP05) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Waste Tunnels (MAP05) Blue","pro":False}]},
{"name":"The Waste Tunnels (MAP05) Red",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Waste Tunnels (MAP05) Main","pro":False}]},
# The Crusher (MAP06)
{"name":"The Crusher (MAP06) Main",
"connects_to_hub":True,
"episode":1,
"connections":[{"target":"The Crusher (MAP06) Blue","pro":False}]},
{"name":"The Crusher (MAP06) Blue",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Crusher (MAP06) Red","pro":False},
{"target":"The Crusher (MAP06) Main","pro":False}]},
{"name":"The Crusher (MAP06) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Crusher (MAP06) Red","pro":False}]},
{"name":"The Crusher (MAP06) Red",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"The Crusher (MAP06) Yellow","pro":False},
{"target":"The Crusher (MAP06) Blue","pro":False},
{"target":"The Crusher (MAP06) Main","pro":False}]},
# Dead Simple (MAP07)
{"name":"Dead Simple (MAP07) Main",
"connects_to_hub":True,
"episode":1,
"connections":[]},
# Tricks and Traps (MAP08)
{"name":"Tricks and Traps (MAP08) Main",
"connects_to_hub":True,
"episode":1,
"connections":[
{"target":"Tricks and Traps (MAP08) Red","pro":False},
{"target":"Tricks and Traps (MAP08) Yellow","pro":False}]},
{"name":"Tricks and Traps (MAP08) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"Tricks and Traps (MAP08) Main","pro":False}]},
{"name":"Tricks and Traps (MAP08) Red",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"Tricks and Traps (MAP08) Main","pro":False}]},
# The Pit (MAP09)
{"name":"The Pit (MAP09) Main",
"connects_to_hub":True,
"episode":1,
"connections":[
{"target":"The Pit (MAP09) Yellow","pro":False},
{"target":"The Pit (MAP09) Blue","pro":False}]},
{"name":"The Pit (MAP09) Blue",
"connects_to_hub":False,
"episode":1,
"connections":[]},
{"name":"The Pit (MAP09) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"The Pit (MAP09) Main","pro":False}]},
# Refueling Base (MAP10)
{"name":"Refueling Base (MAP10) Main",
"connects_to_hub":True,
"episode":1,
"connections":[{"target":"Refueling Base (MAP10) Yellow","pro":False}]},
{"name":"Refueling Base (MAP10) Yellow",
"connects_to_hub":False,
"episode":1,
"connections":[
{"target":"Refueling Base (MAP10) Main","pro":False},
{"target":"Refueling Base (MAP10) Yellow Blue","pro":False}]},
{"name":"Refueling Base (MAP10) Yellow Blue",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"Refueling Base (MAP10) Yellow","pro":False}]},
# Circle of Death (MAP11)
{"name":"Circle of Death (MAP11) Main",
"connects_to_hub":True,
"episode":1,
"connections":[
{"target":"Circle of Death (MAP11) Blue","pro":False},
{"target":"Circle of Death (MAP11) Red","pro":False}]},
{"name":"Circle of Death (MAP11) Blue",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"Circle of Death (MAP11) Main","pro":False}]},
{"name":"Circle of Death (MAP11) Red",
"connects_to_hub":False,
"episode":1,
"connections":[{"target":"Circle of Death (MAP11) Main","pro":False}]},
# The Factory (MAP12)
{"name":"The Factory (MAP12) Main",
"connects_to_hub":True,
"episode":2,
"connections":[
{"target":"The Factory (MAP12) Yellow","pro":False},
{"target":"The Factory (MAP12) Blue","pro":False}]},
{"name":"The Factory (MAP12) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Factory (MAP12) Main","pro":False}]},
{"name":"The Factory (MAP12) Yellow",
"connects_to_hub":False,
"episode":2,
"connections":[]},
# Downtown (MAP13)
{"name":"Downtown (MAP13) Main",
"connects_to_hub":True,
"episode":2,
"connections":[
{"target":"Downtown (MAP13) Yellow","pro":False},
{"target":"Downtown (MAP13) Red","pro":False},
{"target":"Downtown (MAP13) Blue","pro":False}]},
{"name":"Downtown (MAP13) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"Downtown (MAP13) Main","pro":False}]},
{"name":"Downtown (MAP13) Yellow",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"Downtown (MAP13) Main","pro":False}]},
{"name":"Downtown (MAP13) Red",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"Downtown (MAP13) Main","pro":False}]},
# The Inmost Dens (MAP14)
{"name":"The Inmost Dens (MAP14) Main",
"connects_to_hub":True,
"episode":2,
"connections":[{"target":"The Inmost Dens (MAP14) Red","pro":False}]},
{"name":"The Inmost Dens (MAP14) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"The Inmost Dens (MAP14) Main","pro":False},
{"target":"The Inmost Dens (MAP14) Red East","pro":False}]},
{"name":"The Inmost Dens (MAP14) Red",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"The Inmost Dens (MAP14) Main","pro":False},
{"target":"The Inmost Dens (MAP14) Red South","pro":False},
{"target":"The Inmost Dens (MAP14) Red East","pro":False}]},
{"name":"The Inmost Dens (MAP14) Red East",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"The Inmost Dens (MAP14) Blue","pro":False},
{"target":"The Inmost Dens (MAP14) Main","pro":False}]},
{"name":"The Inmost Dens (MAP14) Red South",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Inmost Dens (MAP14) Main","pro":False}]},
# Industrial Zone (MAP15)
{"name":"Industrial Zone (MAP15) Main",
"connects_to_hub":True,
"episode":2,
"connections":[
{"target":"Industrial Zone (MAP15) Yellow East","pro":False},
{"target":"Industrial Zone (MAP15) Yellow West","pro":False}]},
{"name":"Industrial Zone (MAP15) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"Industrial Zone (MAP15) Yellow East","pro":False}]},
{"name":"Industrial Zone (MAP15) Yellow East",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"Industrial Zone (MAP15) Blue","pro":False},
{"target":"Industrial Zone (MAP15) Main","pro":False}]},
{"name":"Industrial Zone (MAP15) Yellow West",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"Industrial Zone (MAP15) Main","pro":False}]},
# Suburbs (MAP16)
{"name":"Suburbs (MAP16) Main",
"connects_to_hub":True,
"episode":2,
"connections":[
{"target":"Suburbs (MAP16) Red","pro":False},
{"target":"Suburbs (MAP16) Blue","pro":False}]},
{"name":"Suburbs (MAP16) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"Suburbs (MAP16) Main","pro":False}]},
{"name":"Suburbs (MAP16) Red",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"Suburbs (MAP16) Main","pro":False}]},
# Tenements (MAP17)
{"name":"Tenements (MAP17) Main",
"connects_to_hub":True,
"episode":2,
"connections":[{"target":"Tenements (MAP17) Red","pro":False}]},
{"name":"Tenements (MAP17) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"Tenements (MAP17) Red","pro":False}]},
{"name":"Tenements (MAP17) Yellow",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"Tenements (MAP17) Red","pro":False},
{"target":"Tenements (MAP17) Blue","pro":False}]},
{"name":"Tenements (MAP17) Red",
"connects_to_hub":False,
"episode":2,
"connections":[
{"target":"Tenements (MAP17) Yellow","pro":False},
{"target":"Tenements (MAP17) Blue","pro":False},
{"target":"Tenements (MAP17) Main","pro":False}]},
# The Courtyard (MAP18)
{"name":"The Courtyard (MAP18) Main",
"connects_to_hub":True,
"episode":2,
"connections":[
{"target":"The Courtyard (MAP18) Yellow","pro":False},
{"target":"The Courtyard (MAP18) Blue","pro":False}]},
{"name":"The Courtyard (MAP18) Blue",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Courtyard (MAP18) Main","pro":False}]},
{"name":"The Courtyard (MAP18) Yellow",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Courtyard (MAP18) Main","pro":False}]},
# The Citadel (MAP19)
{"name":"The Citadel (MAP19) Main",
"connects_to_hub":True,
"episode":2,
"connections":[{"target":"The Citadel (MAP19) Red","pro":False}]},
{"name":"The Citadel (MAP19) Red",
"connects_to_hub":False,
"episode":2,
"connections":[{"target":"The Citadel (MAP19) Main","pro":False}]},
# Gotcha! (MAP20)
{"name":"Gotcha! (MAP20) Main",
"connects_to_hub":True,
"episode":2,
"connections":[]},
# Nirvana (MAP21)
{"name":"Nirvana (MAP21) Main",
"connects_to_hub":True,
"episode":3,
"connections":[{"target":"Nirvana (MAP21) Yellow","pro":False}]},
{"name":"Nirvana (MAP21) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[
{"target":"Nirvana (MAP21) Main","pro":False},
{"target":"Nirvana (MAP21) Magenta","pro":False}]},
{"name":"Nirvana (MAP21) Magenta",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"Nirvana (MAP21) Yellow","pro":False}]},
# The Catacombs (MAP22)
{"name":"The Catacombs (MAP22) Main",
"connects_to_hub":True,
"episode":3,
"connections":[
{"target":"The Catacombs (MAP22) Blue","pro":False},
{"target":"The Catacombs (MAP22) Red","pro":False}]},
{"name":"The Catacombs (MAP22) Blue",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Catacombs (MAP22) Main","pro":False}]},
{"name":"The Catacombs (MAP22) Red",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Catacombs (MAP22) Main","pro":False}]},
# Barrels o Fun (MAP23)
{"name":"Barrels o Fun (MAP23) Main",
"connects_to_hub":True,
"episode":3,
"connections":[{"target":"Barrels o Fun (MAP23) Yellow","pro":False}]},
{"name":"Barrels o Fun (MAP23) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"Barrels o Fun (MAP23) Main","pro":False}]},
# The Chasm (MAP24)
{"name":"The Chasm (MAP24) Main",
"connects_to_hub":True,
"episode":3,
"connections":[{"target":"The Chasm (MAP24) Red","pro":False}]},
{"name":"The Chasm (MAP24) Red",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Chasm (MAP24) Main","pro":False}]},
# Bloodfalls (MAP25)
{"name":"Bloodfalls (MAP25) Main",
"connects_to_hub":True,
"episode":3,
"connections":[{"target":"Bloodfalls (MAP25) Blue","pro":False}]},
{"name":"Bloodfalls (MAP25) Blue",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"Bloodfalls (MAP25) Main","pro":False}]},
# The Abandoned Mines (MAP26)
{"name":"The Abandoned Mines (MAP26) Main",
"connects_to_hub":True,
"episode":3,
"connections":[
{"target":"The Abandoned Mines (MAP26) Yellow","pro":False},
{"target":"The Abandoned Mines (MAP26) Red","pro":False},
{"target":"The Abandoned Mines (MAP26) Blue","pro":False}]},
{"name":"The Abandoned Mines (MAP26) Blue",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Abandoned Mines (MAP26) Main","pro":False}]},
{"name":"The Abandoned Mines (MAP26) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Abandoned Mines (MAP26) Main","pro":False}]},
{"name":"The Abandoned Mines (MAP26) Red",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Abandoned Mines (MAP26) Main","pro":False}]},
# Monster Condo (MAP27)
{"name":"Monster Condo (MAP27) Main",
"connects_to_hub":True,
"episode":3,
"connections":[
{"target":"Monster Condo (MAP27) Yellow","pro":False},
{"target":"Monster Condo (MAP27) Red","pro":False},
{"target":"Monster Condo (MAP27) Blue","pro":False}]},
{"name":"Monster Condo (MAP27) Blue",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"Monster Condo (MAP27) Main","pro":False}]},
{"name":"Monster Condo (MAP27) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"Monster Condo (MAP27) Main","pro":False}]},
{"name":"Monster Condo (MAP27) Red",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"Monster Condo (MAP27) Main","pro":False}]},
# The Spirit World (MAP28)
{"name":"The Spirit World (MAP28) Main",
"connects_to_hub":True,
"episode":3,
"connections":[
{"target":"The Spirit World (MAP28) Yellow","pro":False},
{"target":"The Spirit World (MAP28) Red","pro":False}]},
{"name":"The Spirit World (MAP28) Yellow",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Spirit World (MAP28) Main","pro":False}]},
{"name":"The Spirit World (MAP28) Red",
"connects_to_hub":False,
"episode":3,
"connections":[{"target":"The Spirit World (MAP28) Main","pro":False}]},
# The Living End (MAP29)
{"name":"The Living End (MAP29) Main",
"connects_to_hub":True,
"episode":3,
"connections":[]},
# Icon of Sin (MAP30)
{"name":"Icon of Sin (MAP30) Main",
"connects_to_hub":True,
"episode":3,
"connections":[]},
# Wolfenstein2 (MAP31)
{"name":"Wolfenstein2 (MAP31) Main",
"connects_to_hub":True,
"episode":4,
"connections":[]},
# Grosse2 (MAP32)
{"name":"Grosse2 (MAP32) Main",
"connects_to_hub":True,
"episode":4,
"connections":[]},
]

501
worlds/doom_ii/Rules.py Normal file
View File

@ -0,0 +1,501 @@
# 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 DOOM2World
def set_episode1_rules(player, world, pro):
# Entryway (MAP01)
set_rule(world.get_entrance("Hub -> Entryway (MAP01) Main", player), lambda state:
state.has("Entryway (MAP01)", player, 1))
set_rule(world.get_entrance("Hub -> Entryway (MAP01) Main", player), lambda state:
state.has("Entryway (MAP01)", player, 1))
# Underhalls (MAP02)
set_rule(world.get_entrance("Hub -> Underhalls (MAP02) Main", player), lambda state:
state.has("Underhalls (MAP02)", player, 1))
set_rule(world.get_entrance("Hub -> Underhalls (MAP02) Main", player), lambda state:
state.has("Underhalls (MAP02)", player, 1))
set_rule(world.get_entrance("Hub -> Underhalls (MAP02) Main", player), lambda state:
state.has("Underhalls (MAP02)", player, 1))
set_rule(world.get_entrance("Underhalls (MAP02) Main -> Underhalls (MAP02) Red", player), lambda state:
state.has("Underhalls (MAP02) - Red keycard", player, 1))
set_rule(world.get_entrance("Underhalls (MAP02) Blue -> Underhalls (MAP02) Red", player), lambda state:
state.has("Underhalls (MAP02) - Blue keycard", player, 1))
set_rule(world.get_entrance("Underhalls (MAP02) Red -> Underhalls (MAP02) Blue", player), lambda state:
state.has("Underhalls (MAP02) - Blue keycard", player, 1))
# The Gantlet (MAP03)
set_rule(world.get_entrance("Hub -> The Gantlet (MAP03) Main", player), lambda state:
(state.has("The Gantlet (MAP03)", player, 1)) and
(state.has("Shotgun", player, 1) or
state.has("Chaingun", player, 1) or
state.has("Super Shotgun", player, 1)))
set_rule(world.get_entrance("The Gantlet (MAP03) Main -> The Gantlet (MAP03) Blue", player), lambda state:
state.has("The Gantlet (MAP03) - Blue keycard", player, 1))
set_rule(world.get_entrance("The Gantlet (MAP03) Blue -> The Gantlet (MAP03) Red", player), lambda state:
state.has("The Gantlet (MAP03) - Red keycard", player, 1))
# The Focus (MAP04)
set_rule(world.get_entrance("Hub -> The Focus (MAP04) Main", player), lambda state:
(state.has("The Focus (MAP04)", player, 1)) and
(state.has("Shotgun", player, 1) or
state.has("Chaingun", player, 1) or
state.has("Super Shotgun", player, 1)))
set_rule(world.get_entrance("The Focus (MAP04) Main -> The Focus (MAP04) Red", player), lambda state:
state.has("The Focus (MAP04) - Red keycard", player, 1))
set_rule(world.get_entrance("The Focus (MAP04) Main -> The Focus (MAP04) Blue", player), lambda state:
state.has("The Focus (MAP04) - Blue keycard", player, 1))
set_rule(world.get_entrance("The Focus (MAP04) Yellow -> The Focus (MAP04) Red", player), lambda state:
state.has("The Focus (MAP04) - Yellow keycard", player, 1))
set_rule(world.get_entrance("The Focus (MAP04) Red -> The Focus (MAP04) Yellow", player), lambda state:
state.has("The Focus (MAP04) - Yellow keycard", player, 1))
set_rule(world.get_entrance("The Focus (MAP04) Red -> The Focus (MAP04) Main", player), lambda state:
state.has("The Focus (MAP04) - Red keycard", player, 1))
# The Waste Tunnels (MAP05)
set_rule(world.get_entrance("Hub -> The Waste Tunnels (MAP05) Main", player), lambda state:
(state.has("The Waste Tunnels (MAP05)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("The Waste Tunnels (MAP05) Main -> The Waste Tunnels (MAP05) Red", player), lambda state:
state.has("The Waste Tunnels (MAP05) - Red keycard", player, 1))
set_rule(world.get_entrance("The Waste Tunnels (MAP05) Main -> The Waste Tunnels (MAP05) Blue", player), lambda state:
state.has("The Waste Tunnels (MAP05) - Blue keycard", player, 1))
set_rule(world.get_entrance("The Waste Tunnels (MAP05) Blue -> The Waste Tunnels (MAP05) Yellow", player), lambda state:
state.has("The Waste Tunnels (MAP05) - Yellow keycard", player, 1))
set_rule(world.get_entrance("The Waste Tunnels (MAP05) Blue -> The Waste Tunnels (MAP05) Main", player), lambda state:
state.has("The Waste Tunnels (MAP05) - Blue keycard", player, 1))
set_rule(world.get_entrance("The Waste Tunnels (MAP05) Yellow -> The Waste Tunnels (MAP05) Blue", player), lambda state:
state.has("The Waste Tunnels (MAP05) - Yellow keycard", player, 1))
# The Crusher (MAP06)
set_rule(world.get_entrance("Hub -> The Crusher (MAP06) Main", player), lambda state:
(state.has("The Crusher (MAP06)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("The Crusher (MAP06) Main -> The Crusher (MAP06) Blue", player), lambda state:
state.has("The Crusher (MAP06) - Blue keycard", player, 1))
set_rule(world.get_entrance("The Crusher (MAP06) Blue -> The Crusher (MAP06) Red", player), lambda state:
state.has("The Crusher (MAP06) - Red keycard", player, 1))
set_rule(world.get_entrance("The Crusher (MAP06) Blue -> The Crusher (MAP06) Main", player), lambda state:
state.has("The Crusher (MAP06) - Blue keycard", player, 1))
set_rule(world.get_entrance("The Crusher (MAP06) Yellow -> The Crusher (MAP06) Red", player), lambda state:
state.has("The Crusher (MAP06) - Yellow keycard", player, 1))
set_rule(world.get_entrance("The Crusher (MAP06) Red -> The Crusher (MAP06) Yellow", player), lambda state:
state.has("The Crusher (MAP06) - Yellow keycard", player, 1))
set_rule(world.get_entrance("The Crusher (MAP06) Red -> The Crusher (MAP06) Blue", player), lambda state:
state.has("The Crusher (MAP06) - Red keycard", player, 1))
# Dead Simple (MAP07)
set_rule(world.get_entrance("Hub -> Dead Simple (MAP07) Main", player), lambda state:
(state.has("Dead Simple (MAP07)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
# Tricks and Traps (MAP08)
set_rule(world.get_entrance("Hub -> Tricks and Traps (MAP08) Main", player), lambda state:
(state.has("Tricks and Traps (MAP08)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("Tricks and Traps (MAP08) Main -> Tricks and Traps (MAP08) Red", player), lambda state:
state.has("Tricks and Traps (MAP08) - Red skull key", player, 1))
set_rule(world.get_entrance("Tricks and Traps (MAP08) Main -> Tricks and Traps (MAP08) Yellow", player), lambda state:
state.has("Tricks and Traps (MAP08) - Yellow skull key", player, 1))
# The Pit (MAP09)
set_rule(world.get_entrance("Hub -> The Pit (MAP09) Main", player), lambda state:
(state.has("The Pit (MAP09)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("The Pit (MAP09) Main -> The Pit (MAP09) Yellow", player), lambda state:
state.has("The Pit (MAP09) - Yellow keycard", player, 1))
set_rule(world.get_entrance("The Pit (MAP09) Main -> The Pit (MAP09) Blue", player), lambda state:
state.has("The Pit (MAP09) - Blue keycard", player, 1))
set_rule(world.get_entrance("The Pit (MAP09) Yellow -> The Pit (MAP09) Main", player), lambda state:
state.has("The Pit (MAP09) - Yellow keycard", player, 1))
# Refueling Base (MAP10)
set_rule(world.get_entrance("Hub -> Refueling Base (MAP10) Main", player), lambda state:
(state.has("Refueling Base (MAP10)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("Refueling Base (MAP10) Main -> Refueling Base (MAP10) Yellow", player), lambda state:
state.has("Refueling Base (MAP10) - Yellow keycard", player, 1))
set_rule(world.get_entrance("Refueling Base (MAP10) Yellow -> Refueling Base (MAP10) Yellow Blue", player), lambda state:
state.has("Refueling Base (MAP10) - Blue keycard", player, 1))
# Circle of Death (MAP11)
set_rule(world.get_entrance("Hub -> Circle of Death (MAP11) Main", player), lambda state:
(state.has("Circle of Death (MAP11)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("Circle of Death (MAP11) Main -> Circle of Death (MAP11) Blue", player), lambda state:
state.has("Circle of Death (MAP11) - Blue keycard", player, 1))
set_rule(world.get_entrance("Circle of Death (MAP11) Main -> Circle of Death (MAP11) Red", player), lambda state:
state.has("Circle of Death (MAP11) - Red keycard", player, 1))
def set_episode2_rules(player, world, pro):
# The Factory (MAP12)
set_rule(world.get_entrance("Hub -> The Factory (MAP12) Main", player), lambda state:
(state.has("The Factory (MAP12)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("The Factory (MAP12) Main -> The Factory (MAP12) Yellow", player), lambda state:
state.has("The Factory (MAP12) - Yellow keycard", player, 1))
set_rule(world.get_entrance("The Factory (MAP12) Main -> The Factory (MAP12) Blue", player), lambda state:
state.has("The Factory (MAP12) - Blue keycard", player, 1))
# Downtown (MAP13)
set_rule(world.get_entrance("Hub -> Downtown (MAP13) Main", player), lambda state:
(state.has("Downtown (MAP13)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("Downtown (MAP13) Main -> Downtown (MAP13) Yellow", player), lambda state:
state.has("Downtown (MAP13) - Yellow keycard", player, 1))
set_rule(world.get_entrance("Downtown (MAP13) Main -> Downtown (MAP13) Red", player), lambda state:
state.has("Downtown (MAP13) - Red keycard", player, 1))
set_rule(world.get_entrance("Downtown (MAP13) Main -> Downtown (MAP13) Blue", player), lambda state:
state.has("Downtown (MAP13) - Blue keycard", player, 1))
# The Inmost Dens (MAP14)
set_rule(world.get_entrance("Hub -> The Inmost Dens (MAP14) Main", player), lambda state:
(state.has("The Inmost Dens (MAP14)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("The Inmost Dens (MAP14) Main -> The Inmost Dens (MAP14) Red", player), lambda state:
state.has("The Inmost Dens (MAP14) - Red skull key", player, 1))
set_rule(world.get_entrance("The Inmost Dens (MAP14) Blue -> The Inmost Dens (MAP14) Red East", player), lambda state:
state.has("The Inmost Dens (MAP14) - Blue skull key", player, 1))
set_rule(world.get_entrance("The Inmost Dens (MAP14) Red -> The Inmost Dens (MAP14) Main", player), lambda state:
state.has("The Inmost Dens (MAP14) - Red skull key", player, 1))
set_rule(world.get_entrance("The Inmost Dens (MAP14) Red East -> The Inmost Dens (MAP14) Blue", player), lambda state:
state.has("The Inmost Dens (MAP14) - Blue skull key", player, 1))
# Industrial Zone (MAP15)
set_rule(world.get_entrance("Hub -> Industrial Zone (MAP15) Main", player), lambda state:
(state.has("Industrial Zone (MAP15)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("Industrial Zone (MAP15) Main -> Industrial Zone (MAP15) Yellow East", player), lambda state:
state.has("Industrial Zone (MAP15) - Yellow keycard", player, 1))
set_rule(world.get_entrance("Industrial Zone (MAP15) Main -> Industrial Zone (MAP15) Yellow West", player), lambda state:
state.has("Industrial Zone (MAP15) - Yellow keycard", player, 1))
set_rule(world.get_entrance("Industrial Zone (MAP15) Blue -> Industrial Zone (MAP15) Yellow East", player), lambda state:
state.has("Industrial Zone (MAP15) - Blue keycard", player, 1))
set_rule(world.get_entrance("Industrial Zone (MAP15) Yellow East -> Industrial Zone (MAP15) Blue", player), lambda state:
state.has("Industrial Zone (MAP15) - Blue keycard", player, 1))
# Suburbs (MAP16)
set_rule(world.get_entrance("Hub -> Suburbs (MAP16) Main", player), lambda state:
(state.has("Suburbs (MAP16)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("Suburbs (MAP16) Main -> Suburbs (MAP16) Red", player), lambda state:
state.has("Suburbs (MAP16) - Red skull key", player, 1))
set_rule(world.get_entrance("Suburbs (MAP16) Main -> Suburbs (MAP16) Blue", player), lambda state:
state.has("Suburbs (MAP16) - Blue skull key", player, 1))
# Tenements (MAP17)
set_rule(world.get_entrance("Hub -> Tenements (MAP17) Main", player), lambda state:
(state.has("Tenements (MAP17)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("Tenements (MAP17) Main -> Tenements (MAP17) Red", player), lambda state:
state.has("Tenements (MAP17) - Red keycard", player, 1))
set_rule(world.get_entrance("Tenements (MAP17) Red -> Tenements (MAP17) Yellow", player), lambda state:
state.has("Tenements (MAP17) - Yellow skull key", player, 1))
set_rule(world.get_entrance("Tenements (MAP17) Red -> Tenements (MAP17) Blue", player), lambda state:
state.has("Tenements (MAP17) - Blue keycard", player, 1))
# The Courtyard (MAP18)
set_rule(world.get_entrance("Hub -> The Courtyard (MAP18) Main", player), lambda state:
(state.has("The Courtyard (MAP18)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("The Courtyard (MAP18) Main -> The Courtyard (MAP18) Yellow", player), lambda state:
state.has("The Courtyard (MAP18) - Yellow skull key", player, 1))
set_rule(world.get_entrance("The Courtyard (MAP18) Main -> The Courtyard (MAP18) Blue", player), lambda state:
state.has("The Courtyard (MAP18) - Blue skull key", player, 1))
set_rule(world.get_entrance("The Courtyard (MAP18) Blue -> The Courtyard (MAP18) Main", player), lambda state:
state.has("The Courtyard (MAP18) - Blue skull key", player, 1))
set_rule(world.get_entrance("The Courtyard (MAP18) Yellow -> The Courtyard (MAP18) Main", player), lambda state:
state.has("The Courtyard (MAP18) - Yellow skull key", player, 1))
# The Citadel (MAP19)
set_rule(world.get_entrance("Hub -> The Citadel (MAP19) Main", player), lambda state:
(state.has("The Citadel (MAP19)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("The Citadel (MAP19) Main -> The Citadel (MAP19) Red", player), lambda state:
(state.has("The Citadel (MAP19) - Red skull key", player, 1)) and (state.has("The Citadel (MAP19) - Blue skull key", player, 1) or
state.has("The Citadel (MAP19) - Yellow skull key", player, 1)))
set_rule(world.get_entrance("The Citadel (MAP19) Red -> The Citadel (MAP19) Main", player), lambda state:
(state.has("The Citadel (MAP19) - Red skull key", player, 1)) and (state.has("The Citadel (MAP19) - Yellow skull key", player, 1) or
state.has("The Citadel (MAP19) - Blue skull key", player, 1)))
# Gotcha! (MAP20)
set_rule(world.get_entrance("Hub -> Gotcha! (MAP20) Main", player), lambda state:
(state.has("Gotcha! (MAP20)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
def set_episode3_rules(player, world, pro):
# Nirvana (MAP21)
set_rule(world.get_entrance("Hub -> Nirvana (MAP21) Main", player), lambda state:
(state.has("Nirvana (MAP21)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("Nirvana (MAP21) Main -> Nirvana (MAP21) Yellow", player), lambda state:
state.has("Nirvana (MAP21) - Yellow skull key", player, 1))
set_rule(world.get_entrance("Nirvana (MAP21) Yellow -> Nirvana (MAP21) Main", player), lambda state:
state.has("Nirvana (MAP21) - Yellow skull key", player, 1))
set_rule(world.get_entrance("Nirvana (MAP21) Yellow -> Nirvana (MAP21) Magenta", player), lambda state:
state.has("Nirvana (MAP21) - Red skull key", player, 1) and
state.has("Nirvana (MAP21) - Blue skull key", player, 1))
set_rule(world.get_entrance("Nirvana (MAP21) Magenta -> Nirvana (MAP21) Yellow", player), lambda state:
state.has("Nirvana (MAP21) - Red skull key", player, 1) and
state.has("Nirvana (MAP21) - Blue skull key", player, 1))
# The Catacombs (MAP22)
set_rule(world.get_entrance("Hub -> The Catacombs (MAP22) Main", player), lambda state:
(state.has("The Catacombs (MAP22)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("BFG9000", player, 1) or
state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1)))
set_rule(world.get_entrance("The Catacombs (MAP22) Main -> The Catacombs (MAP22) Blue", player), lambda state:
state.has("The Catacombs (MAP22) - Blue skull key", player, 1))
set_rule(world.get_entrance("The Catacombs (MAP22) Main -> The Catacombs (MAP22) Red", player), lambda state:
state.has("The Catacombs (MAP22) - Red skull key", player, 1))
set_rule(world.get_entrance("The Catacombs (MAP22) Red -> The Catacombs (MAP22) Main", player), lambda state:
state.has("The Catacombs (MAP22) - Red skull key", player, 1))
# Barrels o Fun (MAP23)
set_rule(world.get_entrance("Hub -> Barrels o Fun (MAP23) Main", player), lambda state:
(state.has("Barrels o Fun (MAP23)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
set_rule(world.get_entrance("Barrels o Fun (MAP23) Main -> Barrels o Fun (MAP23) Yellow", player), lambda state:
state.has("Barrels o Fun (MAP23) - Yellow skull key", player, 1))
set_rule(world.get_entrance("Barrels o Fun (MAP23) Yellow -> Barrels o Fun (MAP23) Main", player), lambda state:
state.has("Barrels o Fun (MAP23) - Yellow skull key", player, 1))
# The Chasm (MAP24)
set_rule(world.get_entrance("Hub -> The Chasm (MAP24) Main", player), lambda state:
state.has("The Chasm (MAP24)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Rocket launcher", player, 1) and
state.has("Plasma gun", player, 1) and
state.has("BFG9000", player, 1) and
state.has("Super Shotgun", player, 1))
set_rule(world.get_entrance("The Chasm (MAP24) Main -> The Chasm (MAP24) Red", player), lambda state:
state.has("The Chasm (MAP24) - Red keycard", player, 1))
set_rule(world.get_entrance("The Chasm (MAP24) Red -> The Chasm (MAP24) Main", player), lambda state:
state.has("The Chasm (MAP24) - Red keycard", player, 1))
# Bloodfalls (MAP25)
set_rule(world.get_entrance("Hub -> Bloodfalls (MAP25) Main", player), lambda state:
state.has("Bloodfalls (MAP25)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Rocket launcher", player, 1) and
state.has("Plasma gun", player, 1) and
state.has("BFG9000", player, 1) and
state.has("Super Shotgun", player, 1))
set_rule(world.get_entrance("Bloodfalls (MAP25) Main -> Bloodfalls (MAP25) Blue", player), lambda state:
state.has("Bloodfalls (MAP25) - Blue skull key", player, 1))
set_rule(world.get_entrance("Bloodfalls (MAP25) Blue -> Bloodfalls (MAP25) Main", player), lambda state:
state.has("Bloodfalls (MAP25) - Blue skull key", player, 1))
# The Abandoned Mines (MAP26)
set_rule(world.get_entrance("Hub -> The Abandoned Mines (MAP26) Main", player), lambda state:
state.has("The Abandoned Mines (MAP26)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Rocket launcher", player, 1) and
state.has("BFG9000", player, 1) and
state.has("Plasma gun", player, 1) and
state.has("Super Shotgun", player, 1))
set_rule(world.get_entrance("The Abandoned Mines (MAP26) Main -> The Abandoned Mines (MAP26) Yellow", player), lambda state:
state.has("The Abandoned Mines (MAP26) - Yellow keycard", player, 1))
set_rule(world.get_entrance("The Abandoned Mines (MAP26) Main -> The Abandoned Mines (MAP26) Red", player), lambda state:
state.has("The Abandoned Mines (MAP26) - Red keycard", player, 1))
set_rule(world.get_entrance("The Abandoned Mines (MAP26) Main -> The Abandoned Mines (MAP26) Blue", player), lambda state:
state.has("The Abandoned Mines (MAP26) - Blue keycard", player, 1))
set_rule(world.get_entrance("The Abandoned Mines (MAP26) Blue -> The Abandoned Mines (MAP26) Main", player), lambda state:
state.has("The Abandoned Mines (MAP26) - Blue keycard", player, 1))
set_rule(world.get_entrance("The Abandoned Mines (MAP26) Yellow -> The Abandoned Mines (MAP26) Main", player), lambda state:
state.has("The Abandoned Mines (MAP26) - Yellow keycard", player, 1))
# Monster Condo (MAP27)
set_rule(world.get_entrance("Hub -> Monster Condo (MAP27) Main", player), lambda state:
state.has("Monster Condo (MAP27)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Rocket launcher", player, 1) and
state.has("Plasma gun", player, 1) and
state.has("BFG9000", player, 1) and
state.has("Super Shotgun", player, 1))
set_rule(world.get_entrance("Monster Condo (MAP27) Main -> Monster Condo (MAP27) Yellow", player), lambda state:
state.has("Monster Condo (MAP27) - Yellow skull key", player, 1))
set_rule(world.get_entrance("Monster Condo (MAP27) Main -> Monster Condo (MAP27) Red", player), lambda state:
state.has("Monster Condo (MAP27) - Red skull key", player, 1))
set_rule(world.get_entrance("Monster Condo (MAP27) Main -> Monster Condo (MAP27) Blue", player), lambda state:
state.has("Monster Condo (MAP27) - Blue skull key", player, 1))
set_rule(world.get_entrance("Monster Condo (MAP27) Red -> Monster Condo (MAP27) Main", player), lambda state:
state.has("Monster Condo (MAP27) - Red skull key", player, 1))
# The Spirit World (MAP28)
set_rule(world.get_entrance("Hub -> The Spirit World (MAP28) Main", player), lambda state:
state.has("The Spirit World (MAP28)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Rocket launcher", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Plasma gun", player, 1) and
state.has("BFG9000", player, 1) and
state.has("Super Shotgun", player, 1))
set_rule(world.get_entrance("The Spirit World (MAP28) Main -> The Spirit World (MAP28) Yellow", player), lambda state:
state.has("The Spirit World (MAP28) - Yellow skull key", player, 1))
set_rule(world.get_entrance("The Spirit World (MAP28) Main -> The Spirit World (MAP28) Red", player), lambda state:
state.has("The Spirit World (MAP28) - Red skull key", player, 1))
set_rule(world.get_entrance("The Spirit World (MAP28) Yellow -> The Spirit World (MAP28) Main", player), lambda state:
state.has("The Spirit World (MAP28) - Yellow skull key", player, 1))
set_rule(world.get_entrance("The Spirit World (MAP28) Red -> The Spirit World (MAP28) Main", player), lambda state:
state.has("The Spirit World (MAP28) - Red skull key", player, 1))
# The Living End (MAP29)
set_rule(world.get_entrance("Hub -> The Living End (MAP29) Main", player), lambda state:
state.has("The Living End (MAP29)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Rocket launcher", player, 1) and
state.has("Plasma gun", player, 1) and
state.has("BFG9000", player, 1) and
state.has("Super Shotgun", player, 1))
# Icon of Sin (MAP30)
set_rule(world.get_entrance("Hub -> Icon of Sin (MAP30) Main", player), lambda state:
state.has("Icon of Sin (MAP30)", player, 1) and
state.has("Rocket launcher", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Plasma gun", player, 1) and
state.has("BFG9000", player, 1) and
state.has("Super Shotgun", player, 1))
def set_episode4_rules(player, world, pro):
# Wolfenstein2 (MAP31)
set_rule(world.get_entrance("Hub -> Wolfenstein2 (MAP31) Main", player), lambda state:
(state.has("Wolfenstein2 (MAP31)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
# Grosse2 (MAP32)
set_rule(world.get_entrance("Hub -> Grosse2 (MAP32) Main", player), lambda state:
(state.has("Grosse2 (MAP32)", player, 1) and
state.has("Shotgun", player, 1) and
state.has("Chaingun", player, 1) and
state.has("Super Shotgun", player, 1)) and
(state.has("Rocket launcher", player, 1) or
state.has("Plasma gun", player, 1) or
state.has("BFG9000", player, 1)))
def set_rules(doom_ii_world: "DOOM2World", included_episodes, pro):
player = doom_ii_world.player
world = doom_ii_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)

267
worlds/doom_ii/__init__.py Normal file
View File

@ -0,0 +1,267 @@
import functools
import logging
from typing import Any, Dict, List
from BaseClasses import Entrance, CollectionState, Item, Location, MultiWorld, Region, Tutorial
from worlds.AutoWorld import WebWorld, World
from . import Items, Locations, Maps, Regions, Rules
from .Options import DOOM2Options
logger = logging.getLogger("DOOM II")
DOOM_TYPE_LEVEL_COMPLETE = -2
DOOM_TYPE_COMPUTER_AREA_MAP = 2026
class DOOM2Location(Location):
game: str = "DOOM II"
class DOOM2Item(Item):
game: str = "DOOM II"
class DOOM2Web(WebWorld):
tutorials = [Tutorial(
"Multiworld Setup Guide",
"A guide to setting up the DOOM II randomizer connected to an Archipelago Multiworld",
"English",
"setup_en.md",
"setup/en",
["Daivuk"]
)]
theme = "dirt"
class DOOM2World(World):
"""
Doom II, also known as Doom II: Hell on Earth, is a first-person shooter game by id Software.
It was released for MS-DOS in 1994.
Compared to its predecessor, Doom II features larger levels, new enemies, a new "super shotgun" weapon
"""
options_dataclass = DOOM2Options
options: DOOM2Options
game = "DOOM II"
web = DOOM2Web()
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] = [
"Entryway (MAP01)",
"The Factory (MAP12)",
"Nirvana (MAP21)"
]
# Item ratio that scales depending on episode count. These are the ratio for 3 episode. In DOOM1.
# The ratio have been tweaked seem, and feel good.
items_ratio: Dict[str, float] = {
"Armor": 41,
"Mega Armor": 25,
"Berserk": 12,
"Invulnerability": 10,
"Partial invisibility": 18,
"Supercharge": 28,
"Medikit": 15,
"Box of bullets": 13,
"Box of rockets": 13,
"Box of shotgun shells": 13,
"Energy cell pack": 10
}
def __init__(self, world: MultiWorld, player: int):
self.included_episodes = [1, 1, 1, 0]
self.location_count = 0
super().__init__(world, player)
def get_episode_count(self):
# Don't include 4th, those are secret levels they are additive
return sum(self.included_episodes[:3])
def generate_early(self):
# Cache which episodes are included
self.included_episodes[0] = self.options.episode1.value
self.included_episodes[1] = self.options.episode2.value
self.included_episodes[2] = self.options.episode3.value
self.included_episodes[3] = self.options.episode4.value # 4th episode are secret levels
# If no episodes selected, select Episode 1
if self.get_episode_count() == 0:
self.included_episodes[0] = 1
def create_regions(self):
pro = self.options.pro.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 self.included_episodes[loc["episode"] - 1]
}, DOOM2Location)
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):
for map_name in Maps.map_names:
if map_name + " - Exit" not in self.location_name_to_id:
continue
# Exit location names are in form: Entryway (MAP01) - 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: Entryway (MAP01) - Complete
if not state.has(map_name + " - Complete", self.player, 1):
return False
return True
def set_rules(self):
pro = self.options.pro.value
allow_death_logic = self.options.allow_death_logic.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) -> DOOM2Item:
item_id: int = self.item_name_to_id[name]
return DOOM2Item(name, Items.item_table[item_id]["classification"], item_id, self.player)
def create_items(self):
itempool: List[DOOM2Item] = []
start_with_computer_area_maps: bool = self.options.start_with_computer_area_maps.value
# Items
for item_id, item in Items.item_table.items():
if item["doom_type"] == DOOM_TYPE_LEVEL_COMPLETE:
continue # We'll fill it manually later
if item["doom_type"] == DOOM_TYPE_COMPUTER_AREA_MAP and start_with_computer_area_maps:
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.starting_level_for_episode)):
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 start_with_computer_area_maps:
for item_id, item_dict in Items.item_table.items():
item_episode = item_dict["episode"]
if item_episode > 0:
if item_dict["doom_type"] == DOOM_TYPE_COMPUTER_AREA_MAP 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("Armor", itempool)
self.create_ratioed_items("Mega Armor", itempool)
self.create_ratioed_items("Berserk", itempool)
self.create_ratioed_items("Invulnerability", itempool)
self.create_ratioed_items("Partial invisibility", itempool)
self.create_ratioed_items("Supercharge", 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([
"Medikit",
"Box of bullets",
"Box of rockets",
"Box of shotgun shells",
"Energy cell pack"
])
def create_ratioed_items(self, item_name: str, itempool: List[DOOM2Item]):
remaining_loc = self.location_count - len(itempool)
ep_count = self.get_episode_count()
# Was balanced based on DOOM 1993's first 3 episodes
count = min(remaining_loc, max(1, int(round(self.items_ratio[item_name] * ep_count / 3))))
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]:
return self.options.as_dict("difficulty", "random_monsters", "random_pickups", "random_music", "flip_levels", "allow_death_logic", "pro", "death_link", "reset_level_on_death", "episode1", "episode2", "episode3", "episode4")

View File

@ -0,0 +1,23 @@
# DOOM II
## 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?
Guns, keycards, and level unlocks have been randomized. Typically, you will end up playing different levels out of order to find your keycards 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.
## What is a "check" in DOOM II?
Guns, keycards, and powerups have been replaced with Archipelago checks. The switch at the end of each level is also a check.
## What "items" can you unlock in DOOM II?
Keycards and level unlocks are your main progression items. Gun unlocks and some upgrades are your useful items. Temporary powerups, ammo, healing, and armor are filler items.

View File

@ -0,0 +1,51 @@
# DOOM II Randomizer Setup
## Required Software
- [DOOM II (e.g. Steam version)](https://store.steampowered.com/app/2300/DOOM_II/)
- [Archipelago Crispy DOOM](https://github.com/Daivuk/apdoom/releases)
## Optional Software
- [ArchipelagoTextClient](https://github.com/ArchipelagoMW/Archipelago/releases)
## Installing AP Doom
1. Download [APDOOM.zip](https://github.com/Daivuk/apdoom/releases) and extract it.
2. Copy DOOM2.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. Select `DOOM II` from the drop-down
3. Enter the Archipelago server address, slot name, and password (if you have one)
4. Press "Launch DOOM"
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 DOOM II can be difficult because names are rather long and contain special characters. For example:
```
!hint Underhalls (MAP02) - Red keycard
```
The game has a hint helper implemented, where you can simply type this:
```
!hint map02 red
```
For this to work, include the map short name (`MAP01`), followed by one of the keywords: `map`, `blue`, `yellow`, `red`.
## 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.