Yu-Gi-oh! 2006: implement new game (#2795)
* Initial implementation of Yu-Gi-Oh! WC 2006 * Added Opponents and banlists * Initial implementation of Yu-Gi-Oh! WC 2006 * Added Opponents and banlists * Added Campaign Logic * Added Bonuses Logic * Added challenge logic * fixed yugioh client * ygo06 rom cleanup and include lua * ygo06 patch cleanup * ygo06 move client to world folder * lots of small changes * bug fixes * implemented filler item for yugioh06 * BizHawkClient: Add client and connector * BizHawkClient: Add launcher component and inno_setup lines * BizHawkClient: Misc stability updates and small improvements Bad commit organization a consequence of working with two different branches and not keeping the commits separated * BizHawkClient: Add docstrings * BizHawkClient: Pull in changes from other branch * BizHawkClient: Fix no handler message not displaying after changed ROMs * BizHawkClient: Remove extra print statement from lua * BizHawkClient: Change version command to use raw strings * BizHawkClient: Change script version to single integer * YGO06: added logic for "all expect type forbidden" limited duels * YGO06: Structure Deck choice now affects logic. Fixed a bug with tier 5 campaign opponents. Added logic for TD16 Union. * BizHawkClient: Add newline to version for lua script * BizHawkClient: Call send_connect from BizHawkClient's watcher loop * BizHawkClient: Add handling for failed request getting script version * BizHawkClient: Have base64.lua check lua version explicitly for bit operations On 2.9, it would detect LuaJIT and flood the console with deprecation warnings * BizHawkClient: Update connector script for slightly better errors and address Gambatte frame sync issue * BizHawkClient: Remove accidentally added print statements * BizHawkClient: Fix connector server not closing correctly * BizHawkClient: Move some connector code around, some linting * BizHawkClient: Small cleanup in lua * BizHawkClient: Lua linting * BizHawkClient: Remove outdated sentences in docstrings * YGO06: Logic additions and bug fixes * BizHawkClient: Correctly null check patch file arg * BizHawkClient: Initialize logging * BizHawkClient: Move code to worlds/_bizhawk Also splits out BizHawk communication functions to their own file for use outside this client * BizHawkClient: Add license to connector lua, add types to docs * BizHawkClient: Add module docstrings * YGO06: Logic additions * BizHawkClient: Allow clients to define multiple systems * BizHawkClient: Better logging and handling of interruptions to connection to script * YGO06: Logic additions * YGO06: Added text to options * YGO06: Ported to bizhawk client * YGO06: fix goal not being detected * YGO06: fix access item rule for tier 5 column 1 and 2 * YGO06: docu and bug fixes * YGO06: change name * YGO06: some fixes * YGO06: fix starting opponent and booster not applying * YGO06: added option to reduce the amount of challenges and remove the no ban list from pool. * YGO06: added rom being asked for on first use * YGO06: fix rules for challenges * YGO06: create proper rules for TD04 Ritual Summon * YGO06: mark most banlists as usefull instead of progression * YGO06: reduce the required core boosters across the board * YGO06: fix client not loading if another game already loaded the bizhawk client * YGO06: fix client not finding the bizhawk client. * YGO06: fix TD08 Draw not giving out an item * YGO06: small text changes * YGO06: update to version 0.4.4 * YGO06: logic mixin clean-up * YGO06: added option for campaign opponents as goal * Pokemon Emerald add encounter table randomization * Pokemon Emerald: Item ball randomization working * Pokemon Emerald: Clean up code a little * Pokemon Emerald: Partial rework of region/location creation * Pokemon Emerald: Dedupe items and add more readable names * Refactor region creation to manually defined regions * Split region json * Use new data.json with flattened constants and add HM locations * YGO06: bug fixes * YGO06: bug fix * YGO06: changes default options to be more beginner friendly * YGO06: attempt at universal tracker support. Settings are stored in slot data now. * YGO06: fix for older python versions * YGO06: fix slot data * YGO06: added diiferent opponents to the campaign * YGO06: fix small bug with opponent icons * YGO06: fix unwanted changes * YGO06: repair merge with main * YGO06: map out all of the opponents * YGO06: added opponent shuffle * YGO06: added logic to opponent shuffle * YGO06: added option to use ocg art * YGO06: bug_fixes * YGO06: removed todos, since they are not needed anymore * YGO06: added draft mode * YGO06: added logic to draft mode * YGO06: Added Money multiplier when you lose * YGO06: Fixed Unit Test errors * YGO06: Added Random deck option * YGO06: Bug fix with registering client * YGO06: client clean-up * YGO06: fixed card misspellings * YGO06: removed unused imports and other small changes * YGO06: small changes * YGO06: fix generation error when the combination of starting with "No Banlist" and not adding "No Banlist" to the pool is selected * YGO06: fix ocg art path overwriting Huge Revolution bugfix * YGO06: added comments and other minor changes * YGO06: fixed byte length in client for money * YGO06: fixes for webhost and options * YGO06: use the proper random function * YGO06: change settings to options * YGO06: move to procedure patch * YGO06: fix imports * YGO06: fix download link for patch not showing * YGO06: remove unnecessary Optional * YGO06: fix universal tracker stuff * YGO06: add typings * YGO06: small cleanup * yugioh06: small change to setup Co-authored-by: Scipio Wright <scipiowright@gmail.com> * YGO06: remove logic mixin * YGO06: fix create item and implement create filler and get filler item name * YGO06: remove double lambdas * YGO06: use pkgutil.get_data instaed pf zipFile * YGO06: fix starting items being duplicated * YGO06: lots of small changes * YGO06: moved functions to match execution order * YGO06: run ruff * YGO06: run ruff format * YGO06: fix ruff errors * YGO06: undo ruff format for rules * YGO06: move import to prevent circular dependency * YGO06: remove unused class * YGO06: optimizing rules * YGO06: some optimization and small bug fix --------- Co-authored-by: Zunawe <gyroscope15@gmail.com> Co-authored-by: Scipio Wright <scipiowright@gmail.com>
This commit is contained in:
parent
5fb1d0f98a
commit
539ee1c5da
|
@ -25,6 +25,8 @@ class TestBase(unittest.TestCase):
|
|||
{"medallions", "stones", "rewards", "logic_bottles"},
|
||||
"Starcraft 2":
|
||||
{"Missions", "WoL Missions"},
|
||||
"Yu-Gi-Oh! 2006":
|
||||
{"Campaign Boss Beaten"}
|
||||
}
|
||||
for game_name, world_type in AutoWorldRegister.world_types.items():
|
||||
with self.subTest(game_name, game_name=game_name):
|
||||
|
|
|
@ -0,0 +1,454 @@
|
|||
import os
|
||||
import pkgutil
|
||||
from typing import Any, ClassVar, Dict, List
|
||||
|
||||
import settings
|
||||
from BaseClasses import Entrance, Item, ItemClassification, Location, MultiWorld, Region, Tutorial
|
||||
|
||||
import Utils
|
||||
from worlds.AutoWorld import WebWorld, World
|
||||
|
||||
from .boosterpacks import booster_contents as booster_contents
|
||||
from .boosterpacks import get_booster_locations
|
||||
from .items import (
|
||||
Banlist_Items,
|
||||
booster_packs,
|
||||
draft_boosters,
|
||||
draft_opponents,
|
||||
excluded_items,
|
||||
item_to_index,
|
||||
tier_1_opponents,
|
||||
useful,
|
||||
)
|
||||
from .items import (
|
||||
challenges as challenges,
|
||||
)
|
||||
from .locations import (
|
||||
Bonuses,
|
||||
Campaign_Opponents,
|
||||
Limited_Duels,
|
||||
Required_Cards,
|
||||
Theme_Duels,
|
||||
collection_events,
|
||||
get_beat_challenge_events,
|
||||
special,
|
||||
)
|
||||
from .logic import core_booster, yugioh06_difficulty
|
||||
from .opponents import OpponentData, get_opponent_condition, get_opponent_locations, get_opponents
|
||||
from .opponents import challenge_opponents as challenge_opponents
|
||||
from .options import Yugioh06Options
|
||||
from .rom import MD5America, MD5Europe, YGO06ProcedurePatch, write_tokens
|
||||
from .rom import get_base_rom_path as get_base_rom_path
|
||||
from .rom_values import banlist_ids as banlist_ids
|
||||
from .rom_values import function_addresses as function_addresses
|
||||
from .rom_values import structure_deck_selection as structure_deck_selection
|
||||
from .rules import set_rules
|
||||
from .structure_deck import get_deck_content_locations
|
||||
from .client_bh import YuGiOh2006Client
|
||||
|
||||
|
||||
class Yugioh06Web(WebWorld):
|
||||
theme = "stone"
|
||||
setup = Tutorial(
|
||||
"Multiworld Setup Tutorial",
|
||||
"A guide to setting up Yu-Gi-Oh! - Ultimate Masters Edition - World Championship Tournament 2006 "
|
||||
"for Archipelago on your computer.",
|
||||
"English",
|
||||
"docs/setup_en.md",
|
||||
"setup/en",
|
||||
["Rensen"],
|
||||
)
|
||||
tutorials = [setup]
|
||||
|
||||
|
||||
class Yugioh2006Setting(settings.Group):
|
||||
class Yugioh2006RomFile(settings.UserFilePath):
|
||||
"""File name of your Yu-Gi-Oh 2006 ROM"""
|
||||
|
||||
description = "Yu-Gi-Oh 2006 ROM File"
|
||||
copy_to = "YuGiOh06.gba"
|
||||
md5s = [MD5Europe, MD5America]
|
||||
|
||||
rom_file: Yugioh2006RomFile = Yugioh2006RomFile(Yugioh2006RomFile.copy_to)
|
||||
|
||||
|
||||
class Yugioh06World(World):
|
||||
"""
|
||||
Yu-Gi-Oh! Ultimate Masters: World Championship Tournament 2006 is the definitive Yu-Gi-Oh
|
||||
simulator on the GBA. Featuring over 2000 cards and over 90 Challenges.
|
||||
"""
|
||||
|
||||
game = "Yu-Gi-Oh! 2006"
|
||||
web = Yugioh06Web()
|
||||
options: Yugioh06Options
|
||||
options_dataclass = Yugioh06Options
|
||||
settings_key = "yugioh06_settings"
|
||||
settings: ClassVar[Yugioh2006Setting]
|
||||
|
||||
item_name_to_id = {}
|
||||
start_id = 5730000
|
||||
for k, v in item_to_index.items():
|
||||
item_name_to_id[k] = v + start_id
|
||||
|
||||
location_name_to_id = {}
|
||||
for k, v in Bonuses.items():
|
||||
location_name_to_id[k] = v + start_id
|
||||
|
||||
for k, v in Limited_Duels.items():
|
||||
location_name_to_id[k] = v + start_id
|
||||
|
||||
for k, v in Theme_Duels.items():
|
||||
location_name_to_id[k] = v + start_id
|
||||
|
||||
for k, v in Campaign_Opponents.items():
|
||||
location_name_to_id[k] = v + start_id
|
||||
|
||||
for k, v in special.items():
|
||||
location_name_to_id[k] = v + start_id
|
||||
|
||||
for k, v in Required_Cards.items():
|
||||
location_name_to_id[k] = v + start_id
|
||||
|
||||
item_name_groups = {
|
||||
"Core Booster": core_booster,
|
||||
"Campaign Boss Beaten": ["Tier 1 Beaten", "Tier 2 Beaten", "Tier 3 Beaten", "Tier 4 Beaten", "Tier 5 Beaten"],
|
||||
}
|
||||
|
||||
removed_challenges: List[str]
|
||||
starting_booster: str
|
||||
starting_opponent: str
|
||||
campaign_opponents: List[OpponentData]
|
||||
is_draft_mode: bool
|
||||
|
||||
def __init__(self, world: MultiWorld, player: int):
|
||||
super().__init__(world, player)
|
||||
|
||||
def generate_early(self):
|
||||
self.starting_opponent = ""
|
||||
self.starting_booster = ""
|
||||
self.removed_challenges = []
|
||||
# Universal tracker stuff, shouldn't do anything in standard gen
|
||||
if hasattr(self.multiworld, "re_gen_passthrough"):
|
||||
if "Yu-Gi-Oh! 2006" in self.multiworld.re_gen_passthrough:
|
||||
# bypassing random yaml settings
|
||||
slot_data = self.multiworld.re_gen_passthrough["Yu-Gi-Oh! 2006"]
|
||||
self.options.structure_deck.value = slot_data["structure_deck"]
|
||||
self.options.banlist.value = slot_data["banlist"]
|
||||
self.options.final_campaign_boss_unlock_condition.value = slot_data[
|
||||
"final_campaign_boss_unlock_condition"
|
||||
]
|
||||
self.options.fourth_tier_5_campaign_boss_unlock_condition.value = slot_data[
|
||||
"fourth_tier_5_campaign_boss_unlock_condition"
|
||||
]
|
||||
self.options.third_tier_5_campaign_boss_unlock_condition.value = slot_data[
|
||||
"third_tier_5_campaign_boss_unlock_condition"
|
||||
]
|
||||
self.options.final_campaign_boss_challenges.value = slot_data["final_campaign_boss_challenges"]
|
||||
self.options.fourth_tier_5_campaign_boss_challenges.value = slot_data[
|
||||
"fourth_tier_5_campaign_boss_challenges"
|
||||
]
|
||||
self.options.third_tier_5_campaign_boss_challenges.value = slot_data[
|
||||
"third_tier_5_campaign_boss_challenges"
|
||||
]
|
||||
self.options.final_campaign_boss_campaign_opponents.value = slot_data[
|
||||
"final_campaign_boss_campaign_opponents"
|
||||
]
|
||||
self.options.fourth_tier_5_campaign_boss_campaign_opponents.value = slot_data[
|
||||
"fourth_tier_5_campaign_boss_campaign_opponents"
|
||||
]
|
||||
self.options.third_tier_5_campaign_boss_campaign_opponents.value = slot_data[
|
||||
"third_tier_5_campaign_boss_campaign_opponents"
|
||||
]
|
||||
self.options.number_of_challenges.value = slot_data["number_of_challenges"]
|
||||
self.removed_challenges = slot_data["removed challenges"]
|
||||
self.starting_booster = slot_data["starting_booster"]
|
||||
self.starting_opponent = slot_data["starting_opponent"]
|
||||
|
||||
if self.options.structure_deck.current_key == "none":
|
||||
self.is_draft_mode = True
|
||||
boosters = draft_boosters
|
||||
if self.options.campaign_opponents_shuffle.value:
|
||||
opponents = tier_1_opponents
|
||||
else:
|
||||
opponents = draft_opponents
|
||||
else:
|
||||
self.is_draft_mode = False
|
||||
boosters = booster_packs
|
||||
opponents = tier_1_opponents
|
||||
|
||||
if self.options.structure_deck.current_key == "random_deck":
|
||||
self.options.structure_deck.value = self.random.randint(0, 5)
|
||||
for item in self.options.start_inventory:
|
||||
if item in opponents:
|
||||
self.starting_opponent = item
|
||||
if item in boosters:
|
||||
self.starting_booster = item
|
||||
if not self.starting_opponent:
|
||||
self.starting_opponent = self.random.choice(opponents)
|
||||
self.multiworld.push_precollected(self.create_item(self.starting_opponent))
|
||||
if not self.starting_booster:
|
||||
self.starting_booster = self.random.choice(boosters)
|
||||
self.multiworld.push_precollected(self.create_item(self.starting_booster))
|
||||
banlist = self.options.banlist.value
|
||||
self.multiworld.push_precollected(self.create_item(Banlist_Items[banlist]))
|
||||
|
||||
if not self.removed_challenges:
|
||||
challenge = list((Limited_Duels | Theme_Duels).keys())
|
||||
noc = len(challenge) - max(
|
||||
self.options.third_tier_5_campaign_boss_challenges.value
|
||||
if self.options.third_tier_5_campaign_boss_unlock_condition == "challenges"
|
||||
else 0,
|
||||
self.options.fourth_tier_5_campaign_boss_challenges.value
|
||||
if self.options.fourth_tier_5_campaign_boss_unlock_condition == "challenges"
|
||||
else 0,
|
||||
self.options.final_campaign_boss_challenges.value
|
||||
if self.options.final_campaign_boss_unlock_condition == "challenges"
|
||||
else 0,
|
||||
self.options.number_of_challenges.value,
|
||||
)
|
||||
|
||||
self.random.shuffle(challenge)
|
||||
excluded = self.options.exclude_locations.value.intersection(challenge)
|
||||
prio = self.options.priority_locations.value.intersection(challenge)
|
||||
normal = [e for e in challenge if e not in excluded and e not in prio]
|
||||
total = list(excluded) + normal + list(prio)
|
||||
self.removed_challenges = total[:noc]
|
||||
|
||||
self.campaign_opponents = get_opponents(
|
||||
self.multiworld, self.player, self.options.campaign_opponents_shuffle.value
|
||||
)
|
||||
|
||||
def create_region(self, name: str, locations=None, exits=None):
|
||||
region = Region(name, self.player, self.multiworld)
|
||||
if locations:
|
||||
for location_name, lid in locations.items():
|
||||
if lid is not None and isinstance(lid, int):
|
||||
lid = self.location_name_to_id[location_name]
|
||||
else:
|
||||
lid = None
|
||||
location = Yugioh2006Location(self.player, location_name, lid, region)
|
||||
region.locations.append(location)
|
||||
|
||||
if exits:
|
||||
for _exit in exits:
|
||||
region.exits.append(Entrance(self.player, _exit, region))
|
||||
return region
|
||||
|
||||
def create_regions(self):
|
||||
structure_deck = self.options.structure_deck.current_key
|
||||
self.multiworld.regions += [
|
||||
self.create_region("Menu", None, ["to Deck Edit", "to Campaign", "to Challenges", "to Card Shop"]),
|
||||
self.create_region("Campaign", Bonuses | Campaign_Opponents),
|
||||
self.create_region("Challenges"),
|
||||
self.create_region("Card Shop", Required_Cards | collection_events),
|
||||
self.create_region("Structure Deck", get_deck_content_locations(structure_deck)),
|
||||
]
|
||||
|
||||
self.get_entrance("to Campaign").connect(self.get_region("Campaign"))
|
||||
self.get_entrance("to Challenges").connect(self.get_region("Challenges"))
|
||||
self.get_entrance("to Card Shop").connect(self.get_region("Card Shop"))
|
||||
self.get_entrance("to Deck Edit").connect(self.get_region("Structure Deck"))
|
||||
|
||||
campaign = self.get_region("Campaign")
|
||||
# Campaign Opponents
|
||||
for opponent in self.campaign_opponents:
|
||||
unlock_item = "Campaign Tier " + str(opponent.tier) + " Column " + str(opponent.column)
|
||||
region = self.create_region(opponent.name, get_opponent_locations(opponent))
|
||||
entrance = Entrance(self.player, unlock_item, campaign)
|
||||
if opponent.tier == 5 and opponent.column > 2:
|
||||
unlock_amount = 0
|
||||
is_challenge = True
|
||||
if opponent.column == 3:
|
||||
if self.options.third_tier_5_campaign_boss_unlock_condition.value == 1:
|
||||
unlock_item = "Challenge Beaten"
|
||||
unlock_amount = self.options.third_tier_5_campaign_boss_challenges.value
|
||||
is_challenge = True
|
||||
else:
|
||||
unlock_item = "Campaign Boss Beaten"
|
||||
unlock_amount = self.options.third_tier_5_campaign_boss_campaign_opponents.value
|
||||
is_challenge = False
|
||||
if opponent.column == 4:
|
||||
if self.options.fourth_tier_5_campaign_boss_unlock_condition.value == 1:
|
||||
unlock_item = "Challenge Beaten"
|
||||
unlock_amount = self.options.fourth_tier_5_campaign_boss_challenges.value
|
||||
is_challenge = True
|
||||
else:
|
||||
unlock_item = "Campaign Boss Beaten"
|
||||
unlock_amount = self.options.fourth_tier_5_campaign_boss_campaign_opponents.value
|
||||
is_challenge = False
|
||||
if opponent.column == 5:
|
||||
if self.options.final_campaign_boss_unlock_condition.value == 1:
|
||||
unlock_item = "Challenge Beaten"
|
||||
unlock_amount = self.options.final_campaign_boss_challenges.value
|
||||
is_challenge = True
|
||||
else:
|
||||
unlock_item = "Campaign Boss Beaten"
|
||||
unlock_amount = self.options.final_campaign_boss_campaign_opponents.value
|
||||
is_challenge = False
|
||||
entrance.access_rule = get_opponent_condition(
|
||||
opponent, unlock_item, unlock_amount, self.player, is_challenge
|
||||
)
|
||||
else:
|
||||
entrance.access_rule = lambda state, unlock=unlock_item, opp=opponent: state.has(
|
||||
unlock, self.player
|
||||
) and yugioh06_difficulty(state, self.player, opp.difficulty)
|
||||
campaign.exits.append(entrance)
|
||||
entrance.connect(region)
|
||||
self.multiworld.regions.append(region)
|
||||
|
||||
card_shop = self.get_region("Card Shop")
|
||||
# Booster Contents
|
||||
for booster in booster_packs:
|
||||
region = self.create_region(booster, get_booster_locations(booster))
|
||||
entrance = Entrance(self.player, booster, card_shop)
|
||||
entrance.access_rule = lambda state, unlock=booster: state.has(unlock, self.player)
|
||||
card_shop.exits.append(entrance)
|
||||
entrance.connect(region)
|
||||
self.multiworld.regions.append(region)
|
||||
|
||||
challenge_region = self.get_region("Challenges")
|
||||
# Challenges
|
||||
for challenge, lid in (Limited_Duels | Theme_Duels).items():
|
||||
if challenge in self.removed_challenges:
|
||||
continue
|
||||
region = self.create_region(challenge, {challenge: lid, challenge + " Complete": None})
|
||||
entrance = Entrance(self.player, challenge, challenge_region)
|
||||
entrance.access_rule = lambda state, unlock=challenge: state.has(unlock + " Unlock", self.player)
|
||||
challenge_region.exits.append(entrance)
|
||||
entrance.connect(region)
|
||||
self.multiworld.regions.append(region)
|
||||
|
||||
def create_item(self, name: str) -> Item:
|
||||
classification: ItemClassification = ItemClassification.progression
|
||||
if name == "5000DP":
|
||||
classification = ItemClassification.filler
|
||||
if name in useful:
|
||||
classification = ItemClassification.useful
|
||||
return Item(name, classification, self.item_name_to_id[name], self.player)
|
||||
|
||||
def create_filler(self) -> Item:
|
||||
return self.create_item("5000DP")
|
||||
|
||||
def get_filler_item_name(self) -> str:
|
||||
return "5000DP"
|
||||
|
||||
def create_items(self):
|
||||
start_inventory = self.options.start_inventory.value.copy()
|
||||
item_pool = []
|
||||
items = item_to_index.copy()
|
||||
starting_list = Banlist_Items[self.options.banlist.value]
|
||||
if not self.options.add_empty_banlist.value and starting_list != "No Banlist":
|
||||
items.pop("No Banlist")
|
||||
for rc in self.removed_challenges:
|
||||
items.pop(rc + " Unlock")
|
||||
items.pop(self.starting_opponent)
|
||||
items.pop(self.starting_booster)
|
||||
items.pop(starting_list)
|
||||
for name in items:
|
||||
if name in excluded_items or name in start_inventory:
|
||||
continue
|
||||
item = self.create_item(name)
|
||||
item_pool.append(item)
|
||||
|
||||
needed_item_pool_size = sum(loc not in self.removed_challenges for loc in self.location_name_to_id)
|
||||
needed_filler_amount = needed_item_pool_size - len(item_pool)
|
||||
item_pool += [self.create_item("5000DP") for _ in range(needed_filler_amount)]
|
||||
|
||||
self.multiworld.itempool += item_pool
|
||||
|
||||
for challenge in get_beat_challenge_events(self):
|
||||
item = Yugioh2006Item("Challenge Beaten", ItemClassification.progression, None, self.player)
|
||||
location = self.multiworld.get_location(challenge, self.player)
|
||||
location.place_locked_item(item)
|
||||
|
||||
for opponent in self.campaign_opponents:
|
||||
for location_name, event in get_opponent_locations(opponent).items():
|
||||
if event is not None and not isinstance(event, int):
|
||||
item = Yugioh2006Item(event, ItemClassification.progression, None, self.player)
|
||||
location = self.multiworld.get_location(location_name, self.player)
|
||||
location.place_locked_item(item)
|
||||
|
||||
for booster in booster_packs:
|
||||
for location_name, content in get_booster_locations(booster).items():
|
||||
item = Yugioh2006Item(content, ItemClassification.progression, None, self.player)
|
||||
location = self.multiworld.get_location(location_name, self.player)
|
||||
location.place_locked_item(item)
|
||||
|
||||
structure_deck = self.options.structure_deck.current_key
|
||||
for location_name, content in get_deck_content_locations(structure_deck).items():
|
||||
item = Yugioh2006Item(content, ItemClassification.progression, None, self.player)
|
||||
location = self.multiworld.get_location(location_name, self.player)
|
||||
location.place_locked_item(item)
|
||||
|
||||
for event in collection_events:
|
||||
item = Yugioh2006Item(event, ItemClassification.progression, None, self.player)
|
||||
location = self.multiworld.get_location(event, self.player)
|
||||
location.place_locked_item(item)
|
||||
|
||||
def set_rules(self):
|
||||
set_rules(self)
|
||||
|
||||
def generate_output(self, output_directory: str):
|
||||
outfilepname = f"_P{self.player}"
|
||||
outfilepname += f"_{self.multiworld.get_file_safe_player_name(self.player).replace(' ', '_')}"
|
||||
self.rom_name_text = f'YGO06{Utils.__version__.replace(".", "")[0:3]}_{self.player}_{self.multiworld.seed:11}\0'
|
||||
self.romName = bytearray(self.rom_name_text, "utf8")[:0x20]
|
||||
self.romName.extend([0] * (0x20 - len(self.romName)))
|
||||
self.rom_name = self.romName
|
||||
self.playerName = bytearray(self.multiworld.player_name[self.player], "utf8")[:0x20]
|
||||
self.playerName.extend([0] * (0x20 - len(self.playerName)))
|
||||
patch = YGO06ProcedurePatch(player=self.player, player_name=self.multiworld.player_name[self.player])
|
||||
patch.write_file("base_patch.bsdiff4", pkgutil.get_data(__name__, "patch.bsdiff4"))
|
||||
if self.is_draft_mode:
|
||||
patch.procedure.insert(1, ("apply_bsdiff4", ["draft_patch.bsdiff4"]))
|
||||
patch.write_file("draft_patch.bsdiff4", pkgutil.get_data(__name__, "patches/draft.bsdiff4"))
|
||||
if self.options.ocg_arts:
|
||||
patch.procedure.insert(1, ("apply_bsdiff4", ["ocg_patch.bsdiff4"]))
|
||||
patch.write_file("ocg_patch.bsdiff4", pkgutil.get_data(__name__, "patches/ocg.bsdiff4"))
|
||||
write_tokens(self, patch)
|
||||
|
||||
# Write Output
|
||||
out_file_name = self.multiworld.get_out_file_name_base(self.player)
|
||||
patch.write(os.path.join(output_directory, f"{out_file_name}{patch.patch_file_ending}"))
|
||||
|
||||
def fill_slot_data(self) -> Dict[str, Any]:
|
||||
slot_data: Dict[str, Any] = {
|
||||
"structure_deck": self.options.structure_deck.value,
|
||||
"banlist": self.options.banlist.value,
|
||||
"final_campaign_boss_unlock_condition": self.options.final_campaign_boss_unlock_condition.value,
|
||||
"fourth_tier_5_campaign_boss_unlock_condition":
|
||||
self.options.fourth_tier_5_campaign_boss_unlock_condition.value,
|
||||
"third_tier_5_campaign_boss_unlock_condition":
|
||||
self.options.third_tier_5_campaign_boss_unlock_condition.value,
|
||||
"final_campaign_boss_challenges": self.options.final_campaign_boss_challenges.value,
|
||||
"fourth_tier_5_campaign_boss_challenges":
|
||||
self.options.fourth_tier_5_campaign_boss_challenges.value,
|
||||
"third_tier_5_campaign_boss_challenges":
|
||||
self.options.third_tier_5_campaign_boss_campaign_opponents.value,
|
||||
"final_campaign_boss_campaign_opponents":
|
||||
self.options.final_campaign_boss_campaign_opponents.value,
|
||||
"fourth_tier_5_campaign_boss_campaign_opponents":
|
||||
self.options.fourth_tier_5_campaign_boss_unlock_condition.value,
|
||||
"third_tier_5_campaign_boss_campaign_opponents":
|
||||
self.options.third_tier_5_campaign_boss_campaign_opponents.value,
|
||||
"number_of_challenges": self.options.number_of_challenges.value,
|
||||
}
|
||||
|
||||
slot_data["removed challenges"] = self.removed_challenges
|
||||
slot_data["starting_booster"] = self.starting_booster
|
||||
slot_data["starting_opponent"] = self.starting_opponent
|
||||
return slot_data
|
||||
|
||||
# for the universal tracker, doesn't get called in standard gen
|
||||
@staticmethod
|
||||
def interpret_slot_data(slot_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
# returning slot_data so it regens, giving it back in multiworld.re_gen_passthrough
|
||||
return slot_data
|
||||
|
||||
|
||||
class Yugioh2006Item(Item):
|
||||
game: str = "Yu-Gi-Oh! 2006"
|
||||
|
||||
|
||||
class Yugioh2006Location(Location):
|
||||
game: str = "Yu-Gi-Oh! 2006"
|
|
@ -0,0 +1,923 @@
|
|||
from typing import Dict, Set
|
||||
|
||||
booster_contents: Dict[str, Set[str]] = {
|
||||
"LEGEND OF B.E.W.D.": {
|
||||
"Exodia",
|
||||
"Dark Magician",
|
||||
"Polymerization",
|
||||
"Skull Servant"
|
||||
},
|
||||
"METAL RAIDERS": {
|
||||
"Petit Moth",
|
||||
"Cocoon of Evolution",
|
||||
"Time Wizard",
|
||||
"Gate Guardian",
|
||||
"Kazejin",
|
||||
"Suijin",
|
||||
"Sanga of the Thunder",
|
||||
"Sangan",
|
||||
"Castle of Dark Illusions",
|
||||
"Soul Release",
|
||||
"Magician of Faith",
|
||||
"Dark Elf",
|
||||
"Summoned Skull",
|
||||
"Sangan",
|
||||
"7 Colored Fish",
|
||||
"Tribute to the Doomed",
|
||||
"Horn of Heaven",
|
||||
"Magic Jammer",
|
||||
"Seven Tools of the Bandit",
|
||||
"Solemn Judgment",
|
||||
"Dream Clown",
|
||||
"Heavy Storm"
|
||||
},
|
||||
"PHARAOH'S SERVANT": {
|
||||
"Beast of Talwar",
|
||||
"Jinzo",
|
||||
"Gearfried the Iron Knight",
|
||||
"Harpie's Brother",
|
||||
"Gravity Bind",
|
||||
"Solemn Wishes",
|
||||
"Kiseitai",
|
||||
"Morphing Jar #2",
|
||||
"The Shallow Grave",
|
||||
"Nobleman of Crossout",
|
||||
"Magic Drain"
|
||||
},
|
||||
"PHARAONIC GUARDIAN": {
|
||||
"Don Zaloog",
|
||||
"Reasoning",
|
||||
"Dark Snake Syndrome",
|
||||
"Helpoemer",
|
||||
"Newdoria",
|
||||
"Spirit Reaper",
|
||||
"Yomi Ship",
|
||||
"Pyramid Turtle",
|
||||
"Master Kyonshee",
|
||||
"Book of Life",
|
||||
"Call of the Mummy",
|
||||
"Gravekeeper's Spy",
|
||||
"Gravekeeper's Guard",
|
||||
"A Cat of Ill Omen",
|
||||
"Jowls of Dark Demise",
|
||||
"Non Aggression Area",
|
||||
"Terraforming",
|
||||
"Des Lacooda",
|
||||
"Swarm of Locusts",
|
||||
"Swarm of Scarabs",
|
||||
"Wandering Mummy",
|
||||
"Royal Keeper",
|
||||
"Book of Moon",
|
||||
"Book of Taiyou",
|
||||
"Dust Tornado",
|
||||
"Raigeki Break"
|
||||
},
|
||||
"SPELL RULER": {
|
||||
"Ritual",
|
||||
"Messenger of Peace",
|
||||
"Megamorph",
|
||||
"Shining Angel",
|
||||
"Mystic Tomato",
|
||||
"Giant Rat",
|
||||
"Mother Grizzly",
|
||||
"UFO Turtle",
|
||||
"Flying Kamakiri 1",
|
||||
"Giant Germ",
|
||||
"Nimble Momonga",
|
||||
"Cyber Jar",
|
||||
"Spear Cretin",
|
||||
"Toon Mermaid",
|
||||
"Toon Summoned Skull",
|
||||
"Toon World",
|
||||
"Rush Recklessly",
|
||||
"The Reliable Guardian",
|
||||
"Senju of the Thousand Hands",
|
||||
"Sonic Bird",
|
||||
"Mystical Space Typhoon"
|
||||
},
|
||||
"LABYRINTH OF NIGHTMARE": {
|
||||
"Destiny Board",
|
||||
"Spirit Message 'I'",
|
||||
"Spirit Message 'N'",
|
||||
"Spirit Message 'A'",
|
||||
"Spirit Message 'L'",
|
||||
"Fusion Gate",
|
||||
"Jowgen the Spiritualist",
|
||||
"Fairy Box",
|
||||
"Aqua Spirit",
|
||||
"Rock Spirit",
|
||||
"Spirit of Flames",
|
||||
"Garuda the Wind Spirit",
|
||||
"Hysteric Fairy",
|
||||
"Kycoo the Ghost Destroyer",
|
||||
"Gemini Elf",
|
||||
"Amphibian Beast",
|
||||
"Revival Jam",
|
||||
"Dancing Fairy",
|
||||
"Cure Mermaid",
|
||||
"The Last Warrior from Another Planet",
|
||||
"United We Stand",
|
||||
"Earthbound Spirit",
|
||||
"The Masked Beast"
|
||||
},
|
||||
"LEGACY OF DARKNESS": {
|
||||
"Last Turn",
|
||||
"Yata-Garasu",
|
||||
"Opticlops",
|
||||
"Dark Ruler Ha Des",
|
||||
"Exiled Force",
|
||||
"Injection Fairy Lily",
|
||||
"Spear Dragon",
|
||||
"Luster Dragon #2",
|
||||
"Twin-Headed Behemoth",
|
||||
"Airknight Parshath",
|
||||
"Freed the Matchless General",
|
||||
"Marauding Captain",
|
||||
"Reinforcement of the Army",
|
||||
"Cave Dragon",
|
||||
"Troop Dragon",
|
||||
"Stamping Destruction",
|
||||
"Creature Swap",
|
||||
"Asura Priest",
|
||||
"Fushi No Tori",
|
||||
"Maharaghi",
|
||||
"Susa Soldier",
|
||||
"Emergency Provisions",
|
||||
},
|
||||
"MAGICIAN'S FORCE": {
|
||||
"Huge Revolution",
|
||||
"Oppressed People",
|
||||
"United Resistance",
|
||||
"People Running About",
|
||||
"X-Head Cannon",
|
||||
"Y-Dragon Head",
|
||||
"Z-Metal Tank",
|
||||
"XY-Dragon Cannon",
|
||||
"XZ-Tank Cannon",
|
||||
"YZ-Tank Dragon",
|
||||
"XYZ-Dragon Cannon",
|
||||
"Cliff the Trap Remover",
|
||||
"Wave-Motion Cannon",
|
||||
"Ritual",
|
||||
"Magical Merchant",
|
||||
"Poison of the Old Man",
|
||||
"Chaos Command Magician",
|
||||
"Skilled Dark Magician",
|
||||
"Dark Blade",
|
||||
"Great Angus",
|
||||
"Luster Dragon",
|
||||
"Breaker the magical Warrior",
|
||||
"Old Vindictive Magician",
|
||||
"Apprentice Magician",
|
||||
"Burning Beast",
|
||||
"Freezing Beast",
|
||||
"Pitch-Dark Dragon",
|
||||
"Giant Orc",
|
||||
"Second Goblin",
|
||||
"Decayed Commander",
|
||||
"Zombie Tiger",
|
||||
"Vampire Orchis",
|
||||
"Des Dendle",
|
||||
"Frontline Base",
|
||||
"Formation Union",
|
||||
"Pitch-Black Power Stone",
|
||||
"Magical Marionette",
|
||||
"Royal Magical Library",
|
||||
"Spell Shield Type-8",
|
||||
"Tribute Doll",
|
||||
},
|
||||
"DARK CRISIS": {
|
||||
"Final Countdown",
|
||||
"Ojama Green",
|
||||
"Dark Scorpion Combination",
|
||||
"Dark Scorpion - Chick the Yellow",
|
||||
"Dark Scorpion - Meanae the Thorn",
|
||||
"Dark Scorpion - Gorg the Strong",
|
||||
"Ritual",
|
||||
"Tsukuyomi",
|
||||
"Ojama Trio",
|
||||
"Kaiser Glider",
|
||||
"D.D. Warrior Lady",
|
||||
"Archfiend Soldier",
|
||||
"Skull Archfiend of Lightning",
|
||||
"Blindly Loyal Goblin",
|
||||
"Gagagigo",
|
||||
"Nin-Ken Dog",
|
||||
"Zolga",
|
||||
"Kelbek",
|
||||
"Mudora",
|
||||
"Cestus of Dagla",
|
||||
"Vampire Lord",
|
||||
"Metallizing Parasite - Lunatite",
|
||||
"D. D. Trainer",
|
||||
"Spell Reproduction",
|
||||
"Contract with the Abyss",
|
||||
"Dark Master - Zorc"
|
||||
},
|
||||
"INVASION OF CHAOS": {
|
||||
"Ojama Delta Hurricane",
|
||||
"Ojama Yellow",
|
||||
"Ojama Black",
|
||||
"Heart of the Underdog",
|
||||
"Chaos Emperor Dragon - Envoy of the End",
|
||||
"Self-Destruct Button",
|
||||
"Manticore of Darkness",
|
||||
"Dimension Fusion",
|
||||
"Gigantes",
|
||||
"Inferno",
|
||||
"Silpheed",
|
||||
"Mad Dog of Darkness",
|
||||
"Ryu Kokki",
|
||||
"Berserk Gorilla",
|
||||
"Neo Bug",
|
||||
"Dark Driceratops",
|
||||
"Hyper Hammerhead",
|
||||
"Sea Serpent Warrior of Darkness",
|
||||
"Giga Gagagigo",
|
||||
"Terrorking Salmon",
|
||||
"Blazing Inpachi",
|
||||
"Stealth Bird",
|
||||
"Reload",
|
||||
"Cursed Seal of the Forbidden Spell",
|
||||
"Stray Lambs",
|
||||
"Manju of the Ten Thousand Hands"
|
||||
},
|
||||
"ANCIENT SANCTUARY": {
|
||||
"Monster Gate",
|
||||
"Wall of Revealing Light",
|
||||
"Mystik Wok",
|
||||
"The Agent of Judgment - Saturn",
|
||||
"Zaborg the Thunder Monarch",
|
||||
"Regenerating Mummy",
|
||||
"The End of Anubis",
|
||||
"Solar Flare Dragon",
|
||||
"Level Limit - Area B",
|
||||
"King of the Swamp",
|
||||
"Enemy Controller",
|
||||
"Enchanting Fitting Room"
|
||||
},
|
||||
"SOUL OF THE DUELIST": {
|
||||
"Ninja Grandmaster Sasuke",
|
||||
"Mystic Swordsman LV2",
|
||||
"Mystic Swordsman LV4",
|
||||
"Enraged Muka Muka",
|
||||
"Mobius the Frost Monarch",
|
||||
"Horus the Black Flame Dragon LV6",
|
||||
"Ultimate Baseball Kid",
|
||||
"Armed Dragon LV3",
|
||||
"Armed Dragon LV5",
|
||||
"Masked Dragon",
|
||||
"Element Dragon",
|
||||
"Horus the Black Flame Dragon LV4",
|
||||
"Level Up!",
|
||||
"Howling Insect",
|
||||
"Mobius the Frost Monarch"
|
||||
},
|
||||
"RISE OF DESTINY": {
|
||||
"Homunculus the Alchemic Being",
|
||||
"Thestalos the Firestorm Monarch",
|
||||
"Roc from the Valley of Haze",
|
||||
"Harpie Lady 1",
|
||||
"Silent Swordsman Lv3",
|
||||
"Mystic Swordsman LV6",
|
||||
"Ultimate Insect Lv3",
|
||||
"Divine Wrath",
|
||||
"Serial Spell"
|
||||
},
|
||||
"FLAMING ETERNITY": {
|
||||
"Insect Knight",
|
||||
"Chiron the Mage",
|
||||
"Granmarg the Rock Monarch",
|
||||
"Silent Swordsman Lv5",
|
||||
"The Dark - Hex-Sealed Fusion",
|
||||
"The Earth - Hex-Sealed Fusion",
|
||||
"The Light - Hex-Sealed Fusion",
|
||||
"Ultimate Insect Lv5",
|
||||
"Blast Magician",
|
||||
"Golem Sentry",
|
||||
"Rescue Cat",
|
||||
"Blade Rabbit"
|
||||
},
|
||||
"THE LOST MILLENIUM": {
|
||||
"Ritual",
|
||||
"Megarock Dragon",
|
||||
"D.D. Survivor",
|
||||
"Hieracosphinx",
|
||||
"Elemental Hero Flame Wingman",
|
||||
"Elemental Hero Avian",
|
||||
"Elemental Hero Burstinatrix",
|
||||
"Elemental Hero Clayman",
|
||||
"Elemental Hero Sparkman",
|
||||
"Elemental Hero Thunder Giant",
|
||||
"Aussa the Earth Charmer",
|
||||
"Brain Control"
|
||||
},
|
||||
"CYBERNETIC REVOLUTION": {
|
||||
"Power Bond",
|
||||
"Cyber Dragon",
|
||||
"Cyber Twin Dragon",
|
||||
"Cybernetic Magician",
|
||||
"Indomitable Fighter Lei Lei",
|
||||
"Protective Soul Ailin",
|
||||
"Miracle Fusion",
|
||||
"Elemental Hero Bubbleman",
|
||||
"Jerry Beans Man"
|
||||
},
|
||||
"ELEMENTAL ENERGY": {
|
||||
"V-Tiger Jet",
|
||||
"W-Wing Catapult",
|
||||
"VW-Tiger Catapult",
|
||||
"VWXYZ-Dragon Catapult Cannon",
|
||||
"Zure, Knight of Dark World",
|
||||
"Brron, Mad King of Dark World",
|
||||
"Familiar-Possessed - Aussa",
|
||||
"Familiar-Possessed - Eria",
|
||||
"Familiar-Possessed - Hiita",
|
||||
"Familiar-Possessed - Wynn",
|
||||
"Oxygeddon",
|
||||
"Roll Out!",
|
||||
"Dark World Lightning",
|
||||
"Elemental Hero Rampart Blaster",
|
||||
"Elemental Hero Shining Flare Wingman",
|
||||
"Elemental Hero Wildedge",
|
||||
"Elemental Hero Wildheart",
|
||||
"Elemental Hero Bladedge",
|
||||
"Pot of Avarice",
|
||||
"B.E.S. Tetran"
|
||||
},
|
||||
"SHADOW OF INFINITY": {
|
||||
"Hamon, Lord of Striking Thunder",
|
||||
"Raviel, Lord of Phantasms",
|
||||
"Uria, Lord of Searing Flames",
|
||||
"Ritual",
|
||||
"Treeborn Frog",
|
||||
"Saber Beetle",
|
||||
"Tenkabito Shien",
|
||||
"Princess Pikeru",
|
||||
"Gokipon",
|
||||
"Demise, King of Armageddon",
|
||||
"Anteatereatingant"
|
||||
},
|
||||
"GAME GIFT COLLECTION": {
|
||||
"Ritual",
|
||||
"Valkyrion the Magna Warrior",
|
||||
"Alpha the Magnet Warrior",
|
||||
"Beta the Magnet Warrior",
|
||||
"Gamma the Magnet Warrior",
|
||||
"Magical Blast",
|
||||
"Dunames Dark Witch",
|
||||
"Vorse Raider",
|
||||
"Exarion Universe",
|
||||
"Abyss Soldier",
|
||||
"Slate Warrior",
|
||||
"Cyber-Tech Alligator",
|
||||
"D.D. Assailant",
|
||||
"Goblin Zombie",
|
||||
"Elemental Hero Madballman",
|
||||
"Mind Control",
|
||||
"Toon Dark Magician Girl",
|
||||
"Great Spirit",
|
||||
"Graceful Dice",
|
||||
"Negate Attack",
|
||||
"Foolish Burial",
|
||||
"Card Destruction",
|
||||
"Dark Magic Ritual",
|
||||
"Calamity of the Wicked"
|
||||
},
|
||||
"Special Gift Collection": {
|
||||
"Gate Guardian",
|
||||
"Scapegoat",
|
||||
"Gil Garth",
|
||||
"La Jinn the Mystical Genie of the Lamp",
|
||||
"Summoned Skull",
|
||||
"Inferno Hammer",
|
||||
"Gemini Elf",
|
||||
"Cyber Harpie Lady",
|
||||
"Dandylion",
|
||||
"Blade Knight",
|
||||
"Curse of Vampire",
|
||||
"Elemental Hero Flame Wingman",
|
||||
"Magician of Black Chaos"
|
||||
},
|
||||
"Fairy Collection": {
|
||||
"Silpheed",
|
||||
"Dunames Dark Witch",
|
||||
"Hysteric Fairy",
|
||||
"The Agent of Judgment - Saturn",
|
||||
"Shining Angel",
|
||||
"Airknight Parshath",
|
||||
"Dancing Fairy",
|
||||
"Zolga",
|
||||
"Kelbek",
|
||||
"Mudora",
|
||||
"Protective Soul Ailin",
|
||||
"Marshmallon",
|
||||
"Goddess with the Third Eye",
|
||||
"Asura Priest",
|
||||
"Manju of the Ten Thousand Hands",
|
||||
"Senju of the Thousand Hands"
|
||||
},
|
||||
"Dragon Collection": {
|
||||
"Victory D.",
|
||||
"Chaos Emperor Dragon - Envoy of the End",
|
||||
"Kaiser Glider",
|
||||
"Horus the Black Flame Dragon LV6",
|
||||
"Luster Dragon",
|
||||
"Luster Dragon #2"
|
||||
"Spear Dragon",
|
||||
"Armed Dragon LV3",
|
||||
"Armed Dragon LV5",
|
||||
"Twin-Headed Behemoth",
|
||||
"Cave Dragon",
|
||||
"Masked Dragon",
|
||||
"Element Dragon",
|
||||
"Troop Dragon",
|
||||
"Horus the Black Flame Dragon LV4",
|
||||
"Pitch-Dark Dragon"
|
||||
},
|
||||
"Warrior Collection A": {
|
||||
"Gate Guardian",
|
||||
"Gearfried the Iron Knight",
|
||||
"Dimensional Warrior",
|
||||
"Command Knight",
|
||||
"The Last Warrior from Another Planet",
|
||||
"Dream Clown"
|
||||
},
|
||||
"Warrior Collection B": {
|
||||
"Don Zaloog",
|
||||
"Dark Scorpion - Chick the Yellow",
|
||||
"Dark Scorpion - Meanae the Thorn",
|
||||
"Dark Scorpion - Gorg the Strong",
|
||||
"Cliff the Trap Remover",
|
||||
"Ninja Grandmaster Sasuke",
|
||||
"D.D. Warrior Lady",
|
||||
"Mystic Swordsman LV2",
|
||||
"Mystic Swordsman LV4",
|
||||
"Mystic Swordsman LV6",
|
||||
"Dark Blade",
|
||||
"Blindly Loyal Goblin",
|
||||
"Exiled Force",
|
||||
"Ultimate Baseball Kid",
|
||||
"Freed the Matchless General",
|
||||
"Holy Knight Ishzark",
|
||||
"Silent Swordsman Lv3",
|
||||
"Silent Swordsman Lv5",
|
||||
"Warrior Lady of the Wasteland",
|
||||
"D.D. Assailant",
|
||||
"Blade Knight",
|
||||
"Marauding Captain",
|
||||
"Toon Goblin Attack Force"
|
||||
},
|
||||
"Fiend Collection A": {
|
||||
"Sangan",
|
||||
"Castle of Dark Illusions",
|
||||
"Barox",
|
||||
"La Jinn the Mystical Genie of the Lamp",
|
||||
"Summoned Skull",
|
||||
"Beast of Talwar",
|
||||
"Sangan",
|
||||
"Giant Germ",
|
||||
"Spear Cretin",
|
||||
"Versago the Destroyer",
|
||||
"Toon Summoned Skull"
|
||||
},
|
||||
"Fiend Collection B": {
|
||||
"Raviel, Lord of Phantasms",
|
||||
"Yata-Garasu",
|
||||
"Helpoemer",
|
||||
"Archfiend Soldier",
|
||||
"Skull Descovery Knight",
|
||||
"Gil Garth",
|
||||
"Opticlops",
|
||||
"Zure, Knight of Dark World",
|
||||
"Brron, Mad King of Dark World",
|
||||
"D.D. Survivor",
|
||||
"Skull Archfiend of Lightning",
|
||||
"The End of Anubis",
|
||||
"Dark Ruler Ha Des",
|
||||
"Inferno Hammer",
|
||||
"Legendary Fiend",
|
||||
"Newdoria",
|
||||
"Slate Warrior",
|
||||
"Giant Orc",
|
||||
"Second Goblin",
|
||||
"Kiseitai",
|
||||
"Jowls of Dark Demise",
|
||||
"D. D. Trainer",
|
||||
"Earthbound Spirit"
|
||||
},
|
||||
"Machine Collection A": {
|
||||
"Cyber-Stein",
|
||||
"Mechanicalchaser",
|
||||
"Jinzo",
|
||||
"UFO Turtle",
|
||||
"Cyber-Tech Alligator"
|
||||
},
|
||||
"Machine Collection B": {
|
||||
"X-Head Cannon",
|
||||
"Y-Dragon Head",
|
||||
"Z-Metal Tank",
|
||||
"XY-Dragon Cannon",
|
||||
"XZ-Tank Cannon",
|
||||
"YZ-Tank Dragon",
|
||||
"XYZ-Dragon Cannon",
|
||||
"V-Tiger Jet",
|
||||
"W-Wing Catapult",
|
||||
"VW-Tiger Catapult",
|
||||
"VWXYZ-Dragon Catapult Cannon",
|
||||
"Cyber Dragon",
|
||||
"Cyber Twin Dragon",
|
||||
"Green Gadget",
|
||||
"Red Gadget",
|
||||
"Yellow Gadget",
|
||||
"B.E.S. Tetran"
|
||||
},
|
||||
"Spellcaster Collection A": {
|
||||
"Exodia",
|
||||
"Dark Sage",
|
||||
"Dark Magician",
|
||||
"Time Wizard",
|
||||
"Kazejin",
|
||||
"Magician of Faith",
|
||||
"Dark Elf",
|
||||
"Gemini Elf",
|
||||
"Injection Fairy Lily",
|
||||
"Cosmo Queen",
|
||||
"Magician of Black Chaos"
|
||||
},
|
||||
"Spellcaster Collection B": {
|
||||
"Jowgen the Spiritualist",
|
||||
"Tsukuyomi",
|
||||
"Manticore of Darkness",
|
||||
"Chaos Command Magician",
|
||||
"Cybernetic Magician",
|
||||
"Skilled Dark Magician",
|
||||
"Kycoo the Ghost Destroyer",
|
||||
"Toon Gemini Elf",
|
||||
"Toon Masked Sorcerer",
|
||||
"Toon Dark Magician Girl",
|
||||
"Familiar-Possessed - Aussa",
|
||||
"Familiar-Possessed - Eria",
|
||||
"Familiar-Possessed - Hiita",
|
||||
"Familiar-Possessed - Wynn",
|
||||
"Breaker the magical Warrior",
|
||||
"The Tricky",
|
||||
"Gravekeeper's Spy",
|
||||
"Gravekeeper's Guard",
|
||||
"Summon Priest",
|
||||
"Old Vindictive Magician",
|
||||
"Apprentice Magician",
|
||||
"Princess Pikeru",
|
||||
"Blast Magician",
|
||||
"Magical Marionette",
|
||||
"Mythical Beast Cerberus",
|
||||
"Royal Magical Library",
|
||||
"Aussa the Earth Charmer",
|
||||
|
||||
},
|
||||
"Zombie Collection": {
|
||||
"Skull Servant",
|
||||
"Regenerating Mummy",
|
||||
"Ryu Kokki",
|
||||
"Spirit Reaper",
|
||||
"Pyramid Turtle",
|
||||
"Master Kyonshee",
|
||||
"Curse of Vampire",
|
||||
"Vampire Lord",
|
||||
"Goblin Zombie",
|
||||
"Decayed Commander",
|
||||
"Zombie Tiger",
|
||||
"Des Lacooda",
|
||||
"Wandering Mummy",
|
||||
"Royal Keeper"
|
||||
},
|
||||
"Special Monsters A": {
|
||||
"X-Head Cannon",
|
||||
"Y-Dragon Head",
|
||||
"Z-Metal Tank",
|
||||
"V-Tiger Jet",
|
||||
"W-Wing Catapult",
|
||||
"Yata-Garasu",
|
||||
"Tsukuyomi",
|
||||
"Dark Blade",
|
||||
"Toon Gemini Elf",
|
||||
"Toon Goblin Attack Force",
|
||||
"Toon Masked Sorcerer",
|
||||
"Toon Mermaid",
|
||||
"Toon Dark Magician Girl",
|
||||
"Toon Summoned Skull",
|
||||
"Toon World",
|
||||
"Burning Beast",
|
||||
"Freezing Beast",
|
||||
"Metallizing Parasite - Lunatite",
|
||||
"Pitch-Dark Dragon",
|
||||
"Giant Orc",
|
||||
"Second Goblin",
|
||||
"Decayed Commander",
|
||||
"Zombie Tiger",
|
||||
"Vampire Orchis",
|
||||
"Des Dendle",
|
||||
"Indomitable Fighter Lei Lei",
|
||||
"Protective Soul Ailin",
|
||||
"Frontline Base",
|
||||
"Formation Union",
|
||||
"Roll Out!",
|
||||
"Asura Priest",
|
||||
"Fushi No Tori",
|
||||
"Maharaghi",
|
||||
"Susa Soldier"
|
||||
},
|
||||
"Special Monsters B": {
|
||||
"Polymerization",
|
||||
"Mystic Swordsman LV2",
|
||||
"Mystic Swordsman LV4",
|
||||
"Mystic Swordsman LV6",
|
||||
"Horus the Black Flame Dragon LV6",
|
||||
"Horus the Black Flame Dragon LV4",
|
||||
"Armed Dragon LV3"
|
||||
"Armed Dragon LV5",
|
||||
"Silent Swordsman Lv3",
|
||||
"Silent Swordsman Lv5",
|
||||
"Elemental Hero Flame Wingman",
|
||||
"Elemental Hero Avian",
|
||||
"Elemental Hero Burstinatrix",
|
||||
"Miracle Fusion",
|
||||
"Elemental Hero Madballman",
|
||||
"Elemental Hero Bubbleman",
|
||||
"Elemental Hero Clayman",
|
||||
"Elemental Hero Rampart Blaster",
|
||||
"Elemental Hero Shining Flare Wingman",
|
||||
"Elemental Hero Sparkman",
|
||||
"Elemental Hero Steam Healer",
|
||||
"Elemental Hero Thunder Giant",
|
||||
"Elemental Hero Wildedge",
|
||||
"Elemental Hero Wildheart",
|
||||
"Elemental Hero Bladedge",
|
||||
"Level Up!",
|
||||
"Ultimate Insect Lv3",
|
||||
"Ultimate Insect Lv5"
|
||||
},
|
||||
"Reverse Collection": {
|
||||
"Magical Merchant",
|
||||
"Castle of Dark Illusions",
|
||||
"Magician of Faith",
|
||||
"Penguin Soldier",
|
||||
"Blade Knight",
|
||||
"Gravekeeper's Spy",
|
||||
"Gravekeeper's Guard",
|
||||
"Old Vindictive Magician",
|
||||
"A Cat of Ill Omen",
|
||||
"Jowls of Dark Demise",
|
||||
"Cyber Jar",
|
||||
"Morphing Jar",
|
||||
"Morphing Jar #2",
|
||||
"Needle Worm",
|
||||
"Spear Cretin",
|
||||
"Nobleman of Crossout",
|
||||
"Aussa the Earth Charmer"
|
||||
},
|
||||
"LP Recovery Collection": {
|
||||
"Mystik Wok",
|
||||
"Poison of the Old Man",
|
||||
"Hysteric Fairy",
|
||||
"Dancing Fairy",
|
||||
"Zolga",
|
||||
"Cestus of Dagla",
|
||||
"Nimble Momonga",
|
||||
"Solemn Wishes",
|
||||
"Cure Mermaid",
|
||||
"Princess Pikeru",
|
||||
"Kiseitai",
|
||||
"Elemental Hero Steam Healer",
|
||||
"Fushi No Tori",
|
||||
"Emergency Provisions"
|
||||
},
|
||||
"Special Summon Collection A": {
|
||||
"Perfectly Ultimate Great Moth",
|
||||
"Dark Sage",
|
||||
"Polymerization",
|
||||
"Ritual",
|
||||
"Cyber-Stein",
|
||||
"Scapegoat",
|
||||
"Aqua Spirit",
|
||||
"Rock Spirit",
|
||||
"Spirit of Flames",
|
||||
"Garuda the Wind Spirit",
|
||||
"Shining Angel",
|
||||
"Mystic Tomato",
|
||||
"Giant Rat",
|
||||
"Mother Grizzly",
|
||||
"UFO Turtle",
|
||||
"Flying Kamakiri 1",
|
||||
"Giant Germ",
|
||||
"Revival Jam",
|
||||
"Pyramid Turtle",
|
||||
"Troop Dragon",
|
||||
"Gravekeeper's Spy",
|
||||
"Pitch-Dark Dragon",
|
||||
"Decayed Commander",
|
||||
"Zombie Tiger",
|
||||
"Vampire Orchis",
|
||||
"Des Dendle",
|
||||
"Nimble Momonga",
|
||||
"The Last Warrior from Another Planet",
|
||||
"Embodiment of Apophis",
|
||||
"Cyber Jar",
|
||||
"Morphing Jar #2",
|
||||
"Spear Cretin",
|
||||
"Dark Magic Curtain"
|
||||
},
|
||||
"Special Summon Collection B": {
|
||||
"Monster Gate",
|
||||
"Chaos Emperor Dragon - Envoy of the End",
|
||||
"Ojama Trio",
|
||||
"Dimension Fusion",
|
||||
"Return from the Different Dimension",
|
||||
"Gigantes",
|
||||
"Inferno",
|
||||
"Silpheed",
|
||||
"Mystic Swordsman LV2",
|
||||
"Mystic Swordsman LV4",
|
||||
"Skilled Dark Magician",
|
||||
"Horus the Black Flame Dragon LV6",
|
||||
"Armed Dragon LV3",
|
||||
"Armed Dragon LV5",
|
||||
"Marauding Captain",
|
||||
"Masked Dragon",
|
||||
"The Tricky",
|
||||
"Magical Dimension",
|
||||
"Frontline Base",
|
||||
"Formation Union",
|
||||
"Princess Pikeru",
|
||||
"Skull Zoma",
|
||||
"Metal Reflect Slime"
|
||||
"Level Up!",
|
||||
"Howling Insect",
|
||||
"Tribute Doll",
|
||||
"Enchanting Fitting Room",
|
||||
"Stray Lambs"
|
||||
},
|
||||
"Special Summon Collection C": {
|
||||
"Hamon, Lord of Striking Thunder",
|
||||
"Raviel, Lord of Phantasms",
|
||||
"Uria, Lord of Searing Flames",
|
||||
"Treeborn Frog",
|
||||
"Cyber Dragon",
|
||||
"Familiar-Possessed - Aussa",
|
||||
"Familiar-Possessed - Eria",
|
||||
"Familiar-Possessed - Hiita",
|
||||
"Familiar-Possessed - Wynn",
|
||||
"Silent Swordsman Lv3",
|
||||
"Silent Swordsman Lv5",
|
||||
"Warrior Lady of the Wasteland",
|
||||
"Dandylion",
|
||||
"Curse of Vampire",
|
||||
"Summon Priest",
|
||||
"Miracle Fusion",
|
||||
"Elemental Hero Bubbleman",
|
||||
"The Dark - Hex-Sealed Fusion",
|
||||
"The Earth - Hex-Sealed Fusion",
|
||||
"The Light - Hex-Sealed Fusion",
|
||||
"Ultimate Insect Lv3",
|
||||
"Ultimate Insect Lv5",
|
||||
"Rescue Cat",
|
||||
"Anteatereatingant"
|
||||
},
|
||||
"Equipment Collection": {
|
||||
"Megamorph",
|
||||
"Cestus of Dagla",
|
||||
"United We Stand"
|
||||
},
|
||||
"Continuous Spell/Trap A": {
|
||||
"Destiny Board",
|
||||
"Spirit Message 'I'",
|
||||
"Spirit Message 'N'",
|
||||
"Spirit Message 'A'",
|
||||
"Spirit Message 'L'",
|
||||
"Messenger of Peace",
|
||||
"Fairy Box",
|
||||
"Ultimate Offering",
|
||||
"Gravity Bind",
|
||||
"Solemn Wishes",
|
||||
"Embodiment of Apophis",
|
||||
"Toon World"
|
||||
},
|
||||
"Continuous Spell/Trap B": {
|
||||
"Hamon, Lord of Striking Thunder",
|
||||
"Uria, Lord of Searing Flames",
|
||||
"Wave-Motion Cannon",
|
||||
"Heart of the Underdog",
|
||||
"Wall of Revealing Light",
|
||||
"Dark Snake Syndrome",
|
||||
"Call of the Mummy",
|
||||
"Frontline Base",
|
||||
"Level Limit - Area B",
|
||||
"Skull Zoma",
|
||||
"Pitch-Black Power Stone",
|
||||
"Metal Reflect Slime"
|
||||
},
|
||||
"Quick/Counter Collection": {
|
||||
"Mystik Wok",
|
||||
"Poison of the Old Man",
|
||||
"Scapegoat",
|
||||
"Magical Dimension",
|
||||
"Enemy Controller",
|
||||
"Collapse",
|
||||
"Emergency Provisions",
|
||||
"Graceful Dice",
|
||||
"Offerings to the Doomed",
|
||||
"Reload",
|
||||
"Rush Recklessly",
|
||||
"The Reliable Guardian",
|
||||
"Cursed Seal of the Forbidden Spell",
|
||||
"Divine Wrath",
|
||||
"Horn of Heaven",
|
||||
"Magic Drain",
|
||||
"Magic Jammer",
|
||||
"Negate Attack",
|
||||
"Seven Tools of the Bandit",
|
||||
"Solemn Judgment",
|
||||
"Spell Shield Type-8",
|
||||
"Book of Moon",
|
||||
"Serial Spell",
|
||||
"Mystical Space Typhoon"
|
||||
},
|
||||
"Direct Damage Collection": {
|
||||
"Hamon, Lord of Striking Thunder",
|
||||
"Chaos Emperor Dragon - Envoy of the End",
|
||||
"Dark Snake Syndrome",
|
||||
"Inferno",
|
||||
"Exarion Universe",
|
||||
"Kycoo the Ghost Destroyer",
|
||||
"Giant Germ",
|
||||
"Familiar-Possessed - Aussa",
|
||||
"Familiar-Possessed - Eria",
|
||||
"Familiar-Possessed - Hiita",
|
||||
"Familiar-Possessed - Wynn",
|
||||
"Dark Driceratops",
|
||||
"Saber Beetle",
|
||||
"Thestalos the Firestorm Monarch",
|
||||
"Solar Flare Dragon",
|
||||
"Ultimate Baseball Kid",
|
||||
"Spear Dragon",
|
||||
"Oxygeddon",
|
||||
"Airknight Parshath",
|
||||
"Vampire Lord",
|
||||
"Stamping Destruction",
|
||||
"Decayed Commander",
|
||||
"Jowls of Dark Demise",
|
||||
"Stealth Bird",
|
||||
"Elemental Hero Bladedge",
|
||||
},
|
||||
"Direct Attack Collection": {
|
||||
"Victory D.",
|
||||
"Dark Scorpion Combination",
|
||||
"Spirit Reaper",
|
||||
"Elemental Hero Rampart Blaster",
|
||||
"Toon Gemini Elf",
|
||||
"Toon Goblin Attack Force",
|
||||
"Toon Masked Sorcerer",
|
||||
"Toon Mermaid",
|
||||
"Toon Summoned Skull",
|
||||
"Toon Dark Magician Girl"
|
||||
},
|
||||
"Monster Destroy Collection": {
|
||||
"Hamon, Lord of Striking Thunder",
|
||||
"Inferno",
|
||||
"Ninja Grandmaster Sasuke",
|
||||
"Zaborg the Thunder Monarch",
|
||||
"Mystic Swordsman LV2",
|
||||
"Mystic Swordsman LV4",
|
||||
"Mystic Swordsman LV6",
|
||||
"Skull Descovery Knight",
|
||||
"Inferno Hammer",
|
||||
"Ryu Kokki",
|
||||
"Newdoria",
|
||||
"Exiled Force",
|
||||
"Yomi Ship",
|
||||
"Armed Dragon LV5",
|
||||
"Element Dragon",
|
||||
"Old Vindictive Magician",
|
||||
"Magical Dimension",
|
||||
"Des Dendle",
|
||||
"Nobleman of Crossout",
|
||||
"Shield Crash",
|
||||
"Tribute to the Doomed",
|
||||
"Elemental Hero Flame Wingman",
|
||||
"Elemental Hero Shining Flare Wingman",
|
||||
"Elemental Hero Steam Healer",
|
||||
"Blast Magician",
|
||||
"Magical Marionette",
|
||||
"Swarm of Scarabs",
|
||||
"Offerings to the Doomed",
|
||||
"Divine Wrath",
|
||||
"Dream Clown"
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def get_booster_locations(booster: str) -> Dict[str, str]:
|
||||
return {
|
||||
f"{booster} {i}": content
|
||||
for i, content in enumerate(booster_contents[booster])
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
import math
|
||||
from typing import TYPE_CHECKING, List, Optional, Set
|
||||
|
||||
from NetUtils import ClientStatus, NetworkItem
|
||||
|
||||
import worlds._bizhawk as bizhawk
|
||||
from worlds._bizhawk.client import BizHawkClient
|
||||
from worlds.yugioh06 import item_to_index
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from worlds._bizhawk.context import BizHawkClientContext
|
||||
|
||||
|
||||
class YuGiOh2006Client(BizHawkClient):
|
||||
game = "Yu-Gi-Oh! 2006"
|
||||
system = "GBA"
|
||||
patch_suffix = ".apygo06"
|
||||
local_checked_locations: Set[int]
|
||||
goal_flag: int
|
||||
rom_slot_name: Optional[str]
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.local_checked_locations = set()
|
||||
self.rom_slot_name = None
|
||||
|
||||
async def validate_rom(self, ctx: "BizHawkClientContext") -> bool:
|
||||
from CommonClient import logger
|
||||
|
||||
try:
|
||||
# Check if ROM is some version of Yu-Gi-Oh! 2006
|
||||
game_name = ((await bizhawk.read(ctx.bizhawk_ctx, [(0xA0, 11, "ROM")]))[0]).decode("ascii")
|
||||
if game_name != "YUGIOHWCT06":
|
||||
return False
|
||||
|
||||
# Check if we can read the slot name. Doing this here instead of set_auth as a protection against
|
||||
# validating a ROM where there's no slot name to read.
|
||||
try:
|
||||
slot_name_bytes = (await bizhawk.read(ctx.bizhawk_ctx, [(0x30, 32, "ROM")]))[0]
|
||||
self.rom_slot_name = bytes([byte for byte in slot_name_bytes if byte != 0]).decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
logger.info("Could not read slot name from ROM. Are you sure this ROM matches this client version?")
|
||||
return False
|
||||
except UnicodeDecodeError:
|
||||
return False
|
||||
except bizhawk.RequestFailedError:
|
||||
return False # Should verify on the next pass
|
||||
|
||||
ctx.game = self.game
|
||||
ctx.items_handling = 0b001
|
||||
ctx.want_slot_data = False
|
||||
return True
|
||||
|
||||
async def set_auth(self, ctx: "BizHawkClientContext") -> None:
|
||||
ctx.auth = self.rom_slot_name
|
||||
|
||||
async def game_watcher(self, ctx: "BizHawkClientContext") -> None:
|
||||
try:
|
||||
read_state = await bizhawk.read(
|
||||
ctx.bizhawk_ctx,
|
||||
[
|
||||
(0x0, 8, "EWRAM"),
|
||||
(0x52E8, 32, "EWRAM"),
|
||||
(0x5308, 32, "EWRAM"),
|
||||
(0x5325, 1, "EWRAM"),
|
||||
(0x6C38, 4, "EWRAM"),
|
||||
],
|
||||
)
|
||||
game_state = read_state[0].decode("utf-8")
|
||||
locations = read_state[1]
|
||||
items = read_state[2]
|
||||
amount_items = int.from_bytes(read_state[3], "little")
|
||||
money = int.from_bytes(read_state[4], "little")
|
||||
|
||||
# make sure save was created
|
||||
if game_state != "YWCT2006":
|
||||
return
|
||||
local_items = bytearray(items)
|
||||
await bizhawk.guarded_write(
|
||||
ctx.bizhawk_ctx,
|
||||
[(0x5308, parse_items(bytearray(items), ctx.items_received), "EWRAM")],
|
||||
[(0x5308, local_items, "EWRAM")],
|
||||
)
|
||||
money_received = 0
|
||||
for item in ctx.items_received:
|
||||
if item.item == item_to_index["5000DP"] + 5730000:
|
||||
money_received += 1
|
||||
if money_received > amount_items:
|
||||
await bizhawk.guarded_write(
|
||||
ctx.bizhawk_ctx,
|
||||
[
|
||||
(0x6C38, (money + (money_received - amount_items) * 5000).to_bytes(4, "little"), "EWRAM"),
|
||||
(0x5325, money_received.to_bytes(2, "little"), "EWRAM"),
|
||||
],
|
||||
[
|
||||
(0x6C38, money.to_bytes(4, "little"), "EWRAM"),
|
||||
(0x5325, amount_items.to_bytes(2, "little"), "EWRAM"),
|
||||
],
|
||||
)
|
||||
|
||||
locs_to_send = set()
|
||||
|
||||
# Check for set location flags.
|
||||
for byte_i, byte in enumerate(bytearray(locations)):
|
||||
for i in range(8):
|
||||
and_value = 1 << i
|
||||
if byte & and_value != 0:
|
||||
flag_id = byte_i * 8 + i
|
||||
|
||||
location_id = flag_id + 5730001
|
||||
if location_id in ctx.server_locations:
|
||||
locs_to_send.add(location_id)
|
||||
|
||||
# Send locations if there are any to send.
|
||||
if locs_to_send != self.local_checked_locations:
|
||||
self.local_checked_locations = locs_to_send
|
||||
|
||||
if locs_to_send is not None:
|
||||
await ctx.send_msgs([{"cmd": "LocationChecks", "locations": list(locs_to_send)}])
|
||||
|
||||
# Send game clear if we're in either any ending cutscene or the credits state.
|
||||
if not ctx.finished_game and locations[18] & (1 << 5) != 0:
|
||||
await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}])
|
||||
|
||||
except bizhawk.RequestFailedError:
|
||||
# Exit handler and return to main loop to reconnect.
|
||||
pass
|
||||
|
||||
|
||||
# Parses bit-map for local items and adds the received items to that bit-map
|
||||
def parse_items(local_items: bytearray, items: List[NetworkItem]) -> bytearray:
|
||||
array = local_items
|
||||
for item in items:
|
||||
index = item.item - 5730001
|
||||
if index != 254:
|
||||
byte = math.floor(index / 8)
|
||||
bit = index % 8
|
||||
array[byte] = array[byte] | (1 << bit)
|
||||
return array
|
|
@ -0,0 +1,53 @@
|
|||
# Yu-Gi-Oh! Ultimate Masters: World Championship Tournament 2006
|
||||
|
||||
## Where is the options page?
|
||||
|
||||
The [player options page for this game](../player-options) contains all the options you need to configure and
|
||||
export a config file.
|
||||
|
||||
## What does randomization do to this game?
|
||||
|
||||
Unlocking Booster Packs, Campaign, Limited and Theme Duel Opponents has been changed.
|
||||
You only need to beat each Campaign Opponent once.
|
||||
Logic expects you to have access to the Booster Packs necessary to get the locations at a reasonable pace and consistency.
|
||||
Logic remains, so the game is always able to be completed, but because of the shuffle, the player may need to defeat certain opponents before they
|
||||
would in the vanilla game.
|
||||
|
||||
You can change how much money you receive and how much booster packs cost.
|
||||
|
||||
## What is the goal of Yu-Gi-Oh! 2006 when randomized?
|
||||
|
||||
Defeat a certain amount of Limited/Theme Duels to Unlock the final Campaign Opponent and beat it.
|
||||
|
||||
## What items and locations get shuffled?
|
||||
|
||||
Locations in which items can be found:
|
||||
- Getting a Duel Bonus for the first time
|
||||
- Beating a certain amount campaign opponents of the same level.
|
||||
- Beating a Limited/Theme Duel
|
||||
- Obtaining certain cards (same that unlock a theme duel in vanilla)
|
||||
|
||||
Items that are shuffled:
|
||||
- Unlocking Booster Packs (the "ALL" Booster Packs are excluded)
|
||||
- Unlocking Campaign Opponents
|
||||
- Unlocking Limited/Theme Duels
|
||||
- Banlists
|
||||
|
||||
## What items are _not_ randomized?
|
||||
Certain Key Items are kept in their original locations:
|
||||
- Duel Puzzles
|
||||
- Survival Mode
|
||||
- Booster Pack Contents
|
||||
|
||||
## Which items can be in another player's world?
|
||||
|
||||
Any shuffled item can be in other players' worlds.
|
||||
|
||||
|
||||
## What does another world's item look like in Yu-Gi-Oh! 2006?
|
||||
|
||||
You can only tell when and what you got via the client.
|
||||
|
||||
## When the player receives an item, what happens?
|
||||
|
||||
The Opponent/Pack becomes available to you.
|
|
@ -0,0 +1,72 @@
|
|||
# Setup Guide for Yu-Gi-Oh! Ultimate Masters: World Championship Tournament 2006 Archipelago
|
||||
|
||||
## Important
|
||||
|
||||
As we are using Bizhawk, this guide is only applicable to Windows and Linux systems.
|
||||
|
||||
## Required Software
|
||||
|
||||
- Bizhawk: [Bizhawk Releases from TASVideos](https://tasvideos.org/BizHawk/ReleaseHistory)
|
||||
- Version 2.7.0 and later are supported.
|
||||
- Detailed installation instructions for Bizhawk can be found at the above link.
|
||||
- Windows users must run the prereq installer first, which can also be found at the above link.
|
||||
- The built-in Archipelago client, which can be installed [here](https://github.com/ArchipelagoMW/Archipelago/releases)
|
||||
- A US or European Yu-Gi-Oh! Ultimate Masters: World Championship Tournament 2006 Rom
|
||||
|
||||
## Configuring Bizhawk
|
||||
|
||||
Once Bizhawk has been installed, open Bizhawk and change the following settings:
|
||||
|
||||
- Go to Config > Customize. Switch to the Advanced tab, then switch the Lua Core from "NLua+KopiLua" to
|
||||
"Lua+LuaInterface". This is required for the Lua script to function correctly.
|
||||
**NOTE: Even if "Lua+LuaInterface" is already selected, toggle between the two options and reselect it. Fresh installs**
|
||||
**of newer versions of Bizhawk have a tendency to show "Lua+LuaInterface" as the default selected option but still load**
|
||||
**"NLua+KopiLua" until this step is done.**
|
||||
- Under Config > Customize > Advanced, make sure the box for AutoSaveRAM is checked, and click the 5s button.
|
||||
This reduces the possibility of losing save data in emulator crashes.
|
||||
- Under Config > Customize, check the "Run in background" and "Accept background input" boxes. This will allow you to
|
||||
continue playing in the background, even if another window is selected, such as the Client.
|
||||
- Under Config > Hotkeys, many hotkeys are listed, with many bound to common keys on the keyboard. You will likely want
|
||||
to disable most of these, which you can do quickly using `Esc`.
|
||||
|
||||
It is strongly recommended to associate GBA rom extensions (\*.gba) to the Bizhawk we've just installed.
|
||||
To do so, we simply have to search any GBA rom we happened to own, right click and select "Open with...", unfold
|
||||
the list that appears and select the bottom option "Look for another application", then browse to the Bizhawk folder
|
||||
and select EmuHawk.exe.
|
||||
|
||||
## Configuring your YAML file
|
||||
|
||||
### What is a YAML file and why do I need one?
|
||||
|
||||
Your YAML file contains a set of configuration options which provide the generator with information about how it should
|
||||
generate your game. Each player of a multiworld will provide their own YAML file. This setup allows each player to enjoy
|
||||
an experience customized for their taste, and different players in the same multiworld can all have different options.
|
||||
|
||||
### Where do I get a YAML file?
|
||||
|
||||
You can customize your options by visiting the
|
||||
[Yu-Gi-Oh! 2006 Player Options Page](/games/Yu-Gi-Oh!%202006/player-options)
|
||||
|
||||
## Joining a MultiWorld Game
|
||||
|
||||
### Obtain your GBA patch file
|
||||
|
||||
When you join a multiworld game, you will be asked to provide your YAML file to whoever is hosting. Once that is done,
|
||||
the host will provide you with either a link to download your data file, or with a zip file containing everyone's data
|
||||
files. Your data file should have a `.apygo06` extension.
|
||||
|
||||
Double-click on your `.apygo06` file to start your client and start the ROM patch process. Once the process is finished
|
||||
(this can take a while), the client and the emulator will be started automatically (if you associated the extension
|
||||
to the emulator as recommended).
|
||||
|
||||
### Connect to the Multiserver
|
||||
|
||||
Once both the client and the emulator are started, you must connect them. Within the emulator click on the "Tools"
|
||||
menu and select "Lua Console". Click the folder button or press Ctrl+O to open a Lua script.
|
||||
|
||||
Navigate to your Archipelago install folder and open `data/lua/connector_bizhawk_generic.lua`.
|
||||
|
||||
To connect the client to the multiserver simply put `<address>:<port>` on the textfield on top and press enter (if the
|
||||
server uses password, type in the bottom textfield `/connect <address>:<port> [password]`)
|
||||
|
||||
Don't forget to start manipulating RNG early by shouting "Heart of the Cards!" during generation.
|
|
@ -0,0 +1,72 @@
|
|||
from typing import List, NamedTuple
|
||||
|
||||
|
||||
class FusionData(NamedTuple):
|
||||
name: str
|
||||
materials: List[str]
|
||||
replaceable: bool
|
||||
additional_spells: List[str]
|
||||
|
||||
|
||||
fusions = {
|
||||
"Elemental Hero Flame Wingman": FusionData(
|
||||
"Elemental Hero Flame Wingman",
|
||||
["Elemental Hero Avian", "Elemental Hero Burstinatrix"],
|
||||
True,
|
||||
["Miracle Fusion"]),
|
||||
"Elemental Hero Madballman": FusionData(
|
||||
"Elemental Hero Madballman",
|
||||
["Elemental Hero Bubbleman", "Elemental Hero Clayman"],
|
||||
True,
|
||||
["Miracle Fusion"]),
|
||||
"Elemental Hero Rampart Blaster": FusionData(
|
||||
"Elemental Hero Rampart Blaster",
|
||||
["Elemental Hero Burstinatrix", "Elemental Hero Clayman"],
|
||||
True,
|
||||
["Miracle Fusion"]),
|
||||
"Elemental Hero Shining Flare Wingman": FusionData(
|
||||
"Elemental Hero Shining Flare Wingman",
|
||||
["Elemental Hero Flame Wingman", "Elemental Hero Sparkman"],
|
||||
True,
|
||||
["Miracle Fusion"]),
|
||||
"Elemental Hero Steam Healer": FusionData(
|
||||
"Elemental Hero Steam Healer",
|
||||
["Elemental Hero Burstinatrix", "Elemental Hero Bubbleman"],
|
||||
True,
|
||||
["Miracle Fusion"]),
|
||||
"Elemental Hero Wildedge": FusionData(
|
||||
"Elemental Hero Wildedge",
|
||||
["Elemental Hero Wildheart", "Elemental Hero Bladedge"],
|
||||
True,
|
||||
["Miracle Fusion"])
|
||||
}
|
||||
|
||||
fusion_subs = ["The Dark - Hex-Sealed Fusion",
|
||||
"The Earth - Hex-Sealed Fusion",
|
||||
"The Light - Hex-Sealed Fusion",
|
||||
"Goddess with the Third Eye",
|
||||
"King of the Swamp",
|
||||
"Versago the Destroyer",
|
||||
# Only in All-packs
|
||||
"Beastking of the Swamps",
|
||||
"Mystical Sheep #1"]
|
||||
|
||||
|
||||
def has_all_materials(state, monster, player):
|
||||
data = fusions.get(monster)
|
||||
if not state.has(monster, player):
|
||||
return False
|
||||
if data is None:
|
||||
return True
|
||||
else:
|
||||
materials = data.replaceable and state.has_any(fusion_subs, player)
|
||||
for material in data.materials:
|
||||
materials += has_all_materials(state, material, player)
|
||||
return materials >= len(data.materials)
|
||||
|
||||
|
||||
def count_has_materials(state, monsters, player):
|
||||
amount = 0
|
||||
for monster in monsters:
|
||||
amount += has_all_materials(state, monster, player)
|
||||
return amount
|
|
@ -0,0 +1,369 @@
|
|||
from typing import Dict, List
|
||||
|
||||
item_to_index: Dict[str, int] = {
|
||||
"LEGEND OF B.E.W.D.": 1,
|
||||
"METAL RAIDERS": 2,
|
||||
"PHARAOH'S SERVANT": 3,
|
||||
"PHARAONIC GUARDIAN": 4,
|
||||
"SPELL RULER": 5,
|
||||
"LABYRINTH OF NIGHTMARE": 6,
|
||||
"LEGACY OF DARKNESS": 7,
|
||||
"MAGICIAN'S FORCE": 8,
|
||||
"DARK CRISIS": 9,
|
||||
"INVASION OF CHAOS": 10,
|
||||
"ANCIENT SANCTUARY": 11,
|
||||
"SOUL OF THE DUELIST": 12,
|
||||
"RISE OF DESTINY": 13,
|
||||
"FLAMING ETERNITY": 14,
|
||||
"THE LOST MILLENIUM": 15,
|
||||
"CYBERNETIC REVOLUTION": 16,
|
||||
"ELEMENTAL ENERGY": 17,
|
||||
"SHADOW OF INFINITY": 18,
|
||||
"GAME GIFT COLLECTION": 19,
|
||||
"Special Gift Collection": 20,
|
||||
"Fairy Collection": 21,
|
||||
"Dragon Collection": 22,
|
||||
"Warrior Collection A": 23,
|
||||
"Warrior Collection B": 24,
|
||||
"Fiend Collection A": 25,
|
||||
"Fiend Collection B": 26,
|
||||
"Machine Collection A": 27,
|
||||
"Machine Collection B": 28,
|
||||
"Spellcaster Collection A": 29,
|
||||
"Spellcaster Collection B": 30,
|
||||
"Zombie Collection": 31,
|
||||
"Special Monsters A": 32,
|
||||
"Special Monsters B": 33,
|
||||
"Reverse Collection": 34,
|
||||
"LP Recovery Collection": 35,
|
||||
"Special Summon Collection A": 36,
|
||||
"Special Summon Collection B": 37,
|
||||
"Special Summon Collection C": 38,
|
||||
"Equipment Collection": 39,
|
||||
"Continuous Spell/Trap A": 40,
|
||||
"Continuous Spell/Trap B": 41,
|
||||
"Quick/Counter Collection": 42,
|
||||
"Direct Damage Collection": 43,
|
||||
"Direct Attack Collection": 44,
|
||||
"Monster Destroy Collection": 45,
|
||||
"All Normal Monsters": 46,
|
||||
"All Effect Monsters": 47,
|
||||
"All Fusion Monsters": 48,
|
||||
"All Traps": 49,
|
||||
"All Spells": 50,
|
||||
"All at Random": 51,
|
||||
"LD01 All except Level 4 forbidden Unlock": 52,
|
||||
"LD02 Medium/high Level forbidden Unlock": 53,
|
||||
"LD03 ATK 1500 or more forbidden Unlock": 54,
|
||||
"LD04 Flip Effects forbidden Unlock": 55,
|
||||
"LD05 Tributes forbidden Unlock": 56,
|
||||
"LD06 Traps forbidden Unlock": 57,
|
||||
"LD07 Large Deck A Unlock": 58,
|
||||
"LD08 Large Deck B Unlock": 59,
|
||||
"LD09 Sets Forbidden Unlock": 60,
|
||||
"LD10 All except LV monsters forbidden Unlock": 61,
|
||||
"LD11 All except Fairies forbidden Unlock": 62,
|
||||
"LD12 All except Wind forbidden Unlock": 63,
|
||||
"LD13 All except monsters forbidden Unlock": 64,
|
||||
"LD14 Level 3 or below forbidden Unlock": 65,
|
||||
"LD15 DEF 1500 or less forbidden Unlock": 66,
|
||||
"LD16 Effect Monsters forbidden Unlock": 67,
|
||||
"LD17 Spells forbidden Unlock": 68,
|
||||
"LD18 Attacks forbidden Unlock": 69,
|
||||
"LD19 All except E-Hero's forbidden Unlock": 70,
|
||||
"LD20 All except Warriors forbidden Unlock": 71,
|
||||
"LD21 All except Dark forbidden Unlock": 72,
|
||||
"LD22 All limited cards forbidden Unlock": 73,
|
||||
"LD23 Refer to Mar 05 Banlist Unlock": 74,
|
||||
"LD24 Refer to Sept 04 Banlist Unlock": 75,
|
||||
"LD25 Low Life Points Unlock": 76,
|
||||
"LD26 All except Toons forbidden Unlock": 77,
|
||||
"LD27 All except Spirits forbidden Unlock": 78,
|
||||
"LD28 All except Dragons forbidden Unlock": 79,
|
||||
"LD29 All except Spellcasters forbidden Unlock": 80,
|
||||
"LD30 All except Light forbidden Unlock": 81,
|
||||
"LD31 All except Fire forbidden Unlock": 82,
|
||||
"LD32 Decks with multiples forbidden Unlock": 83,
|
||||
"LD33 Special Summons forbidden Unlock": 84,
|
||||
"LD34 Normal Summons forbidden Unlock": 85,
|
||||
"LD35 All except Zombies forbidden Unlock": 86,
|
||||
"LD36 All except Earth forbidden Unlock": 87,
|
||||
"LD37 All except Water forbidden Unlock": 88,
|
||||
"LD38 Refer to Mar 04 Banlist Unlock": 89,
|
||||
"LD39 Monsters forbidden Unlock": 90,
|
||||
"LD40 Refer to Sept 05 Banlist Unlock": 91,
|
||||
"LD41 Refer to Sept 03 Banlist Unlock": 92,
|
||||
"TD01 Battle Damage Unlock": 93,
|
||||
"TD02 Deflected Damage Unlock": 94,
|
||||
"TD03 Normal Summon Unlock": 95,
|
||||
"TD04 Ritual Summon Unlock": 96,
|
||||
"TD05 Special Summon A Unlock": 97,
|
||||
"TD06 20x Spell Unlock": 98,
|
||||
"TD07 10x Trap Unlock": 99,
|
||||
"TD08 Draw Unlock": 100,
|
||||
"TD09 Hand Destruction Unlock": 101,
|
||||
"TD10 During Opponent's Turn Unlock": 102,
|
||||
"TD11 Recover Unlock": 103,
|
||||
"TD12 Remove Monsters by Effect Unlock": 104,
|
||||
"TD13 Flip Summon Unlock": 105,
|
||||
"TD14 Special Summon B Unlock": 106,
|
||||
"TD15 Token Unlock": 107,
|
||||
"TD16 Union Unlock": 108,
|
||||
"TD17 10x Quick Spell Unlock": 109,
|
||||
"TD18 The Forbidden Unlock": 110,
|
||||
"TD19 20 Turns Unlock": 111,
|
||||
"TD20 Deck Destruction Unlock": 112,
|
||||
"TD21 Victory D. Unlock": 113,
|
||||
"TD22 The Preventers Fight Back Unlock": 114,
|
||||
"TD23 Huge Revolution Unlock": 115,
|
||||
"TD24 Victory in 5 Turns Unlock": 116,
|
||||
"TD25 Moth Grows Up Unlock": 117,
|
||||
"TD26 Magnetic Power Unlock": 118,
|
||||
"TD27 Dark Sage Unlock": 119,
|
||||
"TD28 Direct Damage Unlock": 120,
|
||||
"TD29 Destroy Monsters in Battle Unlock": 121,
|
||||
"TD30 Tribute Summon Unlock": 122,
|
||||
"TD31 Special Summon C Unlock": 123,
|
||||
"TD32 Toon Unlock": 124,
|
||||
"TD33 10x Counter Unlock": 125,
|
||||
"TD34 Destiny Board Unlock": 126,
|
||||
"TD35 Huge Damage in a Turn Unlock": 127,
|
||||
"TD36 V-Z In the House Unlock": 128,
|
||||
"TD37 Uria, Lord of Searing Flames Unlock": 129,
|
||||
"TD38 Hamon, Lord of Striking Thunder Unlock": 130,
|
||||
"TD39 Raviel, Lord of Phantasms Unlock": 131,
|
||||
"TD40 Make a Chain Unlock": 132,
|
||||
"TD41 The Gatekeeper Stands Tall Unlock": 133,
|
||||
"TD42 Serious Damage Unlock": 134,
|
||||
"TD43 Return Monsters with Effects Unlock": 135,
|
||||
"TD44 Fusion Summon Unlock": 136,
|
||||
"TD45 Big Damage at once Unlock": 137,
|
||||
"TD46 XYZ In the House Unlock": 138,
|
||||
"TD47 Spell Counter Unlock": 139,
|
||||
"TD48 Destroy Monsters with Effects Unlock": 140,
|
||||
"TD49 Plunder Unlock": 141,
|
||||
"TD50 Dark Scorpion Combination Unlock": 142,
|
||||
"Campaign Tier 1 Column 1": 143,
|
||||
"Campaign Tier 1 Column 2": 144,
|
||||
"Campaign Tier 1 Column 3": 145,
|
||||
"Campaign Tier 1 Column 4": 146,
|
||||
"Campaign Tier 1 Column 5": 147,
|
||||
"Campaign Tier 2 Column 1": 148,
|
||||
"Campaign Tier 2 Column 2": 149,
|
||||
"Campaign Tier 2 Column 3": 150,
|
||||
"Campaign Tier 2 Column 4": 151,
|
||||
"Campaign Tier 2 Column 5": 152,
|
||||
"Campaign Tier 3 Column 1": 153,
|
||||
"Campaign Tier 3 Column 2": 154,
|
||||
"Campaign Tier 3 Column 3": 155,
|
||||
"Campaign Tier 3 Column 4": 156,
|
||||
"Campaign Tier 3 Column 5": 157,
|
||||
"Campaign Tier 4 Column 1": 158,
|
||||
"Campaign Tier 4 Column 2": 159,
|
||||
"Campaign Tier 4 Column 3": 160,
|
||||
"Campaign Tier 4 Column 4": 161,
|
||||
"Campaign Tier 4 Column 5": 162,
|
||||
"Campaign Tier 5 Column 1": 163,
|
||||
"Campaign Tier 5 Column 2": 164,
|
||||
"No Banlist": 167,
|
||||
"Banlist September 2003": 168,
|
||||
"Banlist March 2004": 169,
|
||||
"Banlist September 2004": 170,
|
||||
"Banlist March 2005": 171,
|
||||
"Banlist September 2005": 172,
|
||||
"5000DP": 254,
|
||||
"Remote": 255,
|
||||
}
|
||||
|
||||
tier_1_opponents: List[str] = [
|
||||
"Campaign Tier 1 Column 1",
|
||||
"Campaign Tier 1 Column 2",
|
||||
"Campaign Tier 1 Column 3",
|
||||
"Campaign Tier 1 Column 4",
|
||||
"Campaign Tier 1 Column 5",
|
||||
]
|
||||
|
||||
Banlist_Items: List[str] = [
|
||||
"No Banlist",
|
||||
"Banlist September 2003",
|
||||
"Banlist March 2004",
|
||||
"Banlist September 2004",
|
||||
"Banlist March 2005",
|
||||
"Banlist September 2005",
|
||||
]
|
||||
|
||||
draft_boosters: List[str] = [
|
||||
"METAL RAIDERS",
|
||||
"PHARAOH'S SERVANT",
|
||||
"PHARAONIC GUARDIAN",
|
||||
"LABYRINTH OF NIGHTMARE",
|
||||
"LEGACY OF DARKNESS",
|
||||
"MAGICIAN'S FORCE",
|
||||
"DARK CRISIS",
|
||||
"INVASION OF CHAOS",
|
||||
"RISE OF DESTINY",
|
||||
"ELEMENTAL ENERGY",
|
||||
"SHADOW OF INFINITY",
|
||||
]
|
||||
|
||||
draft_opponents: List[str] = ["Campaign Tier 1 Column 1", "Campaign Tier 1 Column 5"]
|
||||
|
||||
booster_packs: List[str] = [
|
||||
"LEGEND OF B.E.W.D.",
|
||||
"METAL RAIDERS",
|
||||
"PHARAOH'S SERVANT",
|
||||
"PHARAONIC GUARDIAN",
|
||||
"SPELL RULER",
|
||||
"LABYRINTH OF NIGHTMARE",
|
||||
"LEGACY OF DARKNESS",
|
||||
"MAGICIAN'S FORCE",
|
||||
"DARK CRISIS",
|
||||
"INVASION OF CHAOS",
|
||||
"ANCIENT SANCTUARY",
|
||||
"SOUL OF THE DUELIST",
|
||||
"RISE OF DESTINY",
|
||||
"FLAMING ETERNITY",
|
||||
"THE LOST MILLENIUM",
|
||||
"CYBERNETIC REVOLUTION",
|
||||
"ELEMENTAL ENERGY",
|
||||
"SHADOW OF INFINITY",
|
||||
"GAME GIFT COLLECTION",
|
||||
"Special Gift Collection",
|
||||
"Fairy Collection",
|
||||
"Dragon Collection",
|
||||
"Warrior Collection A",
|
||||
"Warrior Collection B",
|
||||
"Fiend Collection A",
|
||||
"Fiend Collection B",
|
||||
"Machine Collection A",
|
||||
"Machine Collection B",
|
||||
"Spellcaster Collection A",
|
||||
"Spellcaster Collection B",
|
||||
"Zombie Collection",
|
||||
"Special Monsters A",
|
||||
"Special Monsters B",
|
||||
"Reverse Collection",
|
||||
"LP Recovery Collection",
|
||||
"Special Summon Collection A",
|
||||
"Special Summon Collection B",
|
||||
"Special Summon Collection C",
|
||||
"Equipment Collection",
|
||||
"Continuous Spell/Trap A",
|
||||
"Continuous Spell/Trap B",
|
||||
"Quick/Counter Collection",
|
||||
"Direct Damage Collection",
|
||||
"Direct Attack Collection",
|
||||
"Monster Destroy Collection",
|
||||
]
|
||||
|
||||
challenges: List[str] = [
|
||||
"LD01 All except Level 4 forbidden Unlock",
|
||||
"LD02 Medium/high Level forbidden Unlock",
|
||||
"LD03 ATK 1500 or more forbidden Unlock",
|
||||
"LD04 Flip Effects forbidden Unlock",
|
||||
"LD05 Tributes forbidden Unlock",
|
||||
"LD06 Traps forbidden Unlock",
|
||||
"LD07 Large Deck A Unlock",
|
||||
"LD08 Large Deck B Unlock",
|
||||
"LD09 Sets Forbidden Unlock",
|
||||
"LD10 All except LV monsters forbidden Unlock",
|
||||
"LD11 All except Fairies forbidden Unlock",
|
||||
"LD12 All except Wind forbidden Unlock",
|
||||
"LD13 All except monsters forbidden Unlock",
|
||||
"LD14 Level 3 or below forbidden Unlock",
|
||||
"LD15 DEF 1500 or less forbidden Unlock",
|
||||
"LD16 Effect Monsters forbidden Unlock",
|
||||
"LD17 Spells forbidden Unlock",
|
||||
"LD18 Attacks forbidden Unlock",
|
||||
"LD19 All except E-Hero's forbidden Unlock",
|
||||
"LD20 All except Warriors forbidden Unlock",
|
||||
"LD21 All except Dark forbidden Unlock",
|
||||
"LD22 All limited cards forbidden Unlock",
|
||||
"LD23 Refer to Mar 05 Banlist Unlock",
|
||||
"LD24 Refer to Sept 04 Banlist Unlock",
|
||||
"LD25 Low Life Points Unlock",
|
||||
"LD26 All except Toons forbidden Unlock",
|
||||
"LD27 All except Spirits forbidden Unlock",
|
||||
"LD28 All except Dragons forbidden Unlock",
|
||||
"LD29 All except Spellcasters forbidden Unlock",
|
||||
"LD30 All except Light forbidden Unlock",
|
||||
"LD31 All except Fire forbidden Unlock",
|
||||
"LD32 Decks with multiples forbidden Unlock",
|
||||
"LD33 Special Summons forbidden Unlock",
|
||||
"LD34 Normal Summons forbidden Unlock",
|
||||
"LD35 All except Zombies forbidden Unlock",
|
||||
"LD36 All except Earth forbidden Unlock",
|
||||
"LD37 All except Water forbidden Unlock",
|
||||
"LD38 Refer to Mar 04 Banlist Unlock",
|
||||
"LD39 Monsters forbidden Unlock",
|
||||
"LD40 Refer to Sept 05 Banlist Unlock",
|
||||
"LD41 Refer to Sept 03 Banlist Unlock",
|
||||
"TD01 Battle Damage Unlock",
|
||||
"TD02 Deflected Damage Unlock",
|
||||
"TD03 Normal Summon Unlock",
|
||||
"TD04 Ritual Summon Unlock",
|
||||
"TD05 Special Summon A Unlock",
|
||||
"TD06 20x Spell Unlock",
|
||||
"TD07 10x Trap Unlock",
|
||||
"TD08 Draw Unlock",
|
||||
"TD09 Hand Destruction Unlock",
|
||||
"TD10 During Opponent's Turn Unlock",
|
||||
"TD11 Recover Unlock",
|
||||
"TD12 Remove Monsters by Effect Unlock",
|
||||
"TD13 Flip Summon Unlock",
|
||||
"TD14 Special Summon B Unlock",
|
||||
"TD15 Token Unlock",
|
||||
"TD16 Union Unlock",
|
||||
"TD17 10x Quick Spell Unlock",
|
||||
"TD18 The Forbidden Unlock",
|
||||
"TD19 20 Turns Unlock",
|
||||
"TD20 Deck Destruction Unlock",
|
||||
"TD21 Victory D. Unlock",
|
||||
"TD22 The Preventers Fight Back Unlock",
|
||||
"TD23 Huge Revolution Unlock",
|
||||
"TD24 Victory in 5 Turns Unlock",
|
||||
"TD25 Moth Grows Up Unlock",
|
||||
"TD26 Magnetic Power Unlock",
|
||||
"TD27 Dark Sage Unlock",
|
||||
"TD28 Direct Damage Unlock",
|
||||
"TD29 Destroy Monsters in Battle Unlock",
|
||||
"TD30 Tribute Summon Unlock",
|
||||
"TD31 Special Summon C Unlock",
|
||||
"TD32 Toon Unlock",
|
||||
"TD33 10x Counter Unlock",
|
||||
"TD34 Destiny Board Unlock",
|
||||
"TD35 Huge Damage in a Turn Unlock",
|
||||
"TD36 V-Z In the House Unlock",
|
||||
"TD37 Uria, Lord of Searing Flames Unlock",
|
||||
"TD38 Hamon, Lord of Striking Thunder Unlock",
|
||||
"TD39 Raviel, Lord of Phantasms Unlock",
|
||||
"TD40 Make a Chain Unlock",
|
||||
"TD41 The Gatekeeper Stands Tall Unlock",
|
||||
"TD42 Serious Damage Unlock",
|
||||
"TD43 Return Monsters with Effects Unlock",
|
||||
"TD44 Fusion Summon Unlock",
|
||||
"TD45 Big Damage at once Unlock",
|
||||
"TD46 XYZ In the House Unlock",
|
||||
"TD47 Spell Counter Unlock",
|
||||
"TD48 Destroy Monsters with Effects Unlock",
|
||||
"TD49 Plunder Unlock",
|
||||
"TD50 Dark Scorpion Combination Unlock",
|
||||
]
|
||||
|
||||
excluded_items: List[str] = [
|
||||
"All Normal Monsters",
|
||||
"All Effect Monsters",
|
||||
"All Fusion Monsters",
|
||||
"All Traps",
|
||||
"All Spells",
|
||||
"All at Random",
|
||||
"5000DP",
|
||||
"Remote",
|
||||
]
|
||||
|
||||
useful: List[str] = [
|
||||
"Banlist March 2004",
|
||||
"Banlist September 2004",
|
||||
"Banlist March 2005",
|
||||
"Banlist September 2005",
|
||||
]
|
|
@ -0,0 +1,213 @@
|
|||
Bonuses = {
|
||||
"Duelist Bonus Level 1": 1,
|
||||
"Duelist Bonus Level 2": 2,
|
||||
"Duelist Bonus Level 3": 3,
|
||||
"Duelist Bonus Level 4": 4,
|
||||
"Duelist Bonus Level 5": 5,
|
||||
"Battle Damage": 6,
|
||||
"Battle Damage Only Bonus": 7,
|
||||
"Max ATK Bonus": 8,
|
||||
"Max Damage Bonus": 9,
|
||||
"Destroyed in Battle Bonus": 10,
|
||||
"Spell Card Bonus": 11,
|
||||
"Trap Card Bonus": 12,
|
||||
"Tribute Summon Bonus": 13,
|
||||
"Fusion Summon Bonus": 14,
|
||||
"Ritual Summon Bonus": 15,
|
||||
"No Special Summon Bonus": 16,
|
||||
"No Spell Cards Bonus": 17,
|
||||
"No Trap Cards Bonus": 18,
|
||||
"No Damage Bonus": 19,
|
||||
"Over 20000 LP Bonus": 20,
|
||||
"Low LP Bonus": 21,
|
||||
"Extremely Low LP Bonus": 22,
|
||||
"Low Deck Bonus": 23,
|
||||
"Extremely Low Deck Bonus": 24,
|
||||
"Effect Damage Only Bonus": 25,
|
||||
"No More Cards Bonus": 26,
|
||||
"Opponent's Turn Finish Bonus": 27,
|
||||
"Exactly 0 LP Bonus": 28,
|
||||
"Reversal Finish Bonus": 29,
|
||||
"Quick Finish Bonus": 30,
|
||||
"Exodia Finish Bonus": 31,
|
||||
"Last Turn Finish Bonus": 32,
|
||||
"Final Countdown Finish Bonus": 33,
|
||||
"Destiny Board Finish Bonus": 34,
|
||||
"Yata-Garasu Finish Bonus": 35,
|
||||
"Skull Servant Finish Bonus": 36,
|
||||
"Konami Bonus": 37,
|
||||
}
|
||||
|
||||
Limited_Duels = {
|
||||
"LD01 All except Level 4 forbidden": 38,
|
||||
"LD02 Medium/high Level forbidden": 39,
|
||||
"LD03 ATK 1500 or more forbidden": 40,
|
||||
"LD04 Flip Effects forbidden": 41,
|
||||
"LD05 Tributes forbidden": 42,
|
||||
"LD06 Traps forbidden": 43,
|
||||
"LD07 Large Deck A": 44,
|
||||
"LD08 Large Deck B": 45,
|
||||
"LD09 Sets Forbidden": 46,
|
||||
"LD10 All except LV monsters forbidden": 47,
|
||||
"LD11 All except Fairies forbidden": 48,
|
||||
"LD12 All except Wind forbidden": 49,
|
||||
"LD13 All except monsters forbidden": 50,
|
||||
"LD14 Level 3 or below forbidden": 51,
|
||||
"LD15 DEF 1500 or less forbidden": 52,
|
||||
"LD16 Effect Monsters forbidden": 53,
|
||||
"LD17 Spells forbidden": 54,
|
||||
"LD18 Attacks forbidden": 55,
|
||||
"LD19 All except E-Hero's forbidden": 56,
|
||||
"LD20 All except Warriors forbidden": 57,
|
||||
"LD21 All except Dark forbidden": 58,
|
||||
"LD22 All limited cards forbidden": 59,
|
||||
"LD23 Refer to Mar 05 Banlist": 60,
|
||||
"LD24 Refer to Sept 04 Banlist": 61,
|
||||
"LD25 Low Life Points": 62,
|
||||
"LD26 All except Toons forbidden": 63,
|
||||
"LD27 All except Spirits forbidden": 64,
|
||||
"LD28 All except Dragons forbidden": 65,
|
||||
"LD29 All except Spellcasters forbidden": 66,
|
||||
"LD30 All except Light forbidden": 67,
|
||||
"LD31 All except Fire forbidden": 68,
|
||||
"LD32 Decks with multiples forbidden": 69,
|
||||
"LD33 Special Summons forbidden": 70,
|
||||
"LD34 Normal Summons forbidden": 71,
|
||||
"LD35 All except Zombies forbidden": 72,
|
||||
"LD36 All except Earth forbidden": 73,
|
||||
"LD37 All except Water forbidden": 74,
|
||||
"LD38 Refer to Mar 04 Banlist": 75,
|
||||
"LD39 Monsters forbidden": 76,
|
||||
"LD40 Refer to Sept 05 Banlist": 77,
|
||||
"LD41 Refer to Sept 03 Banlist": 78,
|
||||
}
|
||||
|
||||
Theme_Duels = {
|
||||
"TD01 Battle Damage": 79,
|
||||
"TD02 Deflected Damage": 80,
|
||||
"TD03 Normal Summon": 81,
|
||||
"TD04 Ritual Summon": 82,
|
||||
"TD05 Special Summon A": 83,
|
||||
"TD06 20x Spell": 84,
|
||||
"TD07 10x Trap": 85,
|
||||
"TD08 Draw": 86,
|
||||
"TD09 Hand Destruction": 87,
|
||||
"TD10 During Opponent's Turn": 88,
|
||||
"TD11 Recover": 89,
|
||||
"TD12 Remove Monsters by Effect": 90,
|
||||
"TD13 Flip Summon": 91,
|
||||
"TD14 Special Summon B": 92,
|
||||
"TD15 Token": 93,
|
||||
"TD16 Union": 94,
|
||||
"TD17 10x Quick Spell": 95,
|
||||
"TD18 The Forbidden": 96,
|
||||
"TD19 20 Turns": 97,
|
||||
"TD20 Deck Destruction": 98,
|
||||
"TD21 Victory D.": 99,
|
||||
"TD22 The Preventers Fight Back": 100,
|
||||
"TD23 Huge Revolution": 101,
|
||||
"TD24 Victory in 5 Turns": 102,
|
||||
"TD25 Moth Grows Up": 103,
|
||||
"TD26 Magnetic Power": 104,
|
||||
"TD27 Dark Sage": 105,
|
||||
"TD28 Direct Damage": 106,
|
||||
"TD29 Destroy Monsters in Battle": 107,
|
||||
"TD30 Tribute Summon": 108,
|
||||
"TD31 Special Summon C": 109,
|
||||
"TD32 Toon": 110,
|
||||
"TD33 10x Counter": 111,
|
||||
"TD34 Destiny Board": 112,
|
||||
"TD35 Huge Damage in a Turn": 113,
|
||||
"TD36 V-Z In the House": 114,
|
||||
"TD37 Uria, Lord of Searing Flames": 115,
|
||||
"TD38 Hamon, Lord of Striking Thunder": 116,
|
||||
"TD39 Raviel, Lord of Phantasms": 117,
|
||||
"TD40 Make a Chain": 118,
|
||||
"TD41 The Gatekeeper Stands Tall": 119,
|
||||
"TD42 Serious Damage": 120,
|
||||
"TD43 Return Monsters with Effects": 121,
|
||||
"TD44 Fusion Summon": 122,
|
||||
"TD45 Big Damage at once": 123,
|
||||
"TD46 XYZ In the House": 124,
|
||||
"TD47 Spell Counter": 125,
|
||||
"TD48 Destroy Monsters with Effects": 126,
|
||||
"TD49 Plunder": 127,
|
||||
"TD50 Dark Scorpion Combination": 128,
|
||||
}
|
||||
|
||||
Campaign_Opponents = {
|
||||
"Campaign Tier 1: 1 Win": 129,
|
||||
"Campaign Tier 1: 3 Wins A": 130,
|
||||
"Campaign Tier 1: 3 Wins B": 131,
|
||||
"Campaign Tier 1: 5 Wins A": 132,
|
||||
"Campaign Tier 1: 5 Wins B": 133,
|
||||
"Campaign Tier 2: 1 Win": 134,
|
||||
"Campaign Tier 2: 3 Wins A": 135,
|
||||
"Campaign Tier 2: 3 Wins B": 136,
|
||||
"Campaign Tier 2: 5 Wins A": 137,
|
||||
"Campaign Tier 2: 5 Wins B": 138,
|
||||
"Campaign Tier 3: 1 Win": 139,
|
||||
"Campaign Tier 3: 3 Wins A": 140,
|
||||
"Campaign Tier 3: 3 Wins B": 141,
|
||||
"Campaign Tier 3: 5 Wins A": 142,
|
||||
"Campaign Tier 3: 5 Wins B": 143,
|
||||
"Campaign Tier 4: 5 Wins A": 144,
|
||||
"Campaign Tier 4: 5 Wins B": 145,
|
||||
}
|
||||
|
||||
special = {
|
||||
"Campaign Tier 5: Column 1 Win": 146,
|
||||
"Campaign Tier 5: Column 2 Win": 147,
|
||||
"Campaign Tier 5: Column 3 Win": 148,
|
||||
"Campaign Tier 5: Column 4 Win": 149,
|
||||
# "Campaign Final Boss Win": 150,
|
||||
}
|
||||
|
||||
Required_Cards = {
|
||||
"Obtain all pieces of Exodia": 154,
|
||||
"Obtain Final Countdown": 155,
|
||||
"Obtain Victory Dragon": 156,
|
||||
"Obtain Ojama Delta Hurricane and its required cards": 157,
|
||||
"Obtain Huge Revolution and its required cards": 158,
|
||||
"Obtain Perfectly Ultimate Great Moth and its required cards": 159,
|
||||
"Obtain Valkyrion the Magna Warrior and its pieces": 160,
|
||||
"Obtain Dark Sage and its required cards": 161,
|
||||
"Obtain Destiny Board and its letters": 162,
|
||||
"Obtain all XYZ-Dragon Cannon fusions and their materials": 163,
|
||||
"Obtain VWXYZ-Dragon Catapult Cannon and the fusion materials": 164,
|
||||
"Obtain Hamon, Lord of Striking Thunder": 165,
|
||||
"Obtain Raviel, Lord of Phantasms": 166,
|
||||
"Obtain Uria, Lord of Searing Flames": 167,
|
||||
"Obtain Gate Guardian and its pieces": 168,
|
||||
"Obtain Dark Scorpion Combination and its required cards": 169,
|
||||
}
|
||||
|
||||
collection_events = {
|
||||
"Ojama Delta Hurricane and required cards": None,
|
||||
"Huge Revolution and its required cards": None,
|
||||
"Perfectly Ultimate Great Moth and its required cards": None,
|
||||
"Valkyrion the Magna Warrior and its pieces": None,
|
||||
"Dark Sage and its required cards": None,
|
||||
"Destiny Board and its letters": None,
|
||||
"XYZ-Dragon Cannon fusions and their materials": None,
|
||||
"VWXYZ-Dragon Catapult Cannon and the fusion materials": None,
|
||||
"Gate Guardian and its pieces": None,
|
||||
"Dark Scorpion Combination and its required cards": None,
|
||||
"Can Exodia Win": None,
|
||||
"Can Yata Lock": None,
|
||||
"Can Stall with Monsters": None,
|
||||
"Can Stall with ST": None,
|
||||
"Can Last Turn Win": None,
|
||||
"Has Back-row removal": None,
|
||||
}
|
||||
|
||||
|
||||
def get_beat_challenge_events(self):
|
||||
beat_events = {}
|
||||
for limited in Limited_Duels.keys():
|
||||
if limited not in self.removed_challenges:
|
||||
beat_events[limited + " Complete"] = None
|
||||
for theme in Theme_Duels.keys():
|
||||
if theme not in self.removed_challenges:
|
||||
beat_events[theme + " Complete"] = None
|
||||
return beat_events
|
|
@ -0,0 +1,28 @@
|
|||
from typing import List
|
||||
|
||||
from BaseClasses import CollectionState
|
||||
|
||||
core_booster: List[str] = [
|
||||
"LEGEND OF B.E.W.D.",
|
||||
"METAL RAIDERS",
|
||||
"PHARAOH'S SERVANT",
|
||||
"PHARAONIC GUARDIAN",
|
||||
"SPELL RULER",
|
||||
"LABYRINTH OF NIGHTMARE",
|
||||
"LEGACY OF DARKNESS",
|
||||
"MAGICIAN'S FORCE",
|
||||
"DARK CRISIS",
|
||||
"INVASION OF CHAOS",
|
||||
"ANCIENT SANCTUARY",
|
||||
"SOUL OF THE DUELIST",
|
||||
"RISE OF DESTINY",
|
||||
"FLAMING ETERNITY",
|
||||
"THE LOST MILLENIUM",
|
||||
"CYBERNETIC REVOLUTION",
|
||||
"ELEMENTAL ENERGY",
|
||||
"SHADOW OF INFINITY",
|
||||
]
|
||||
|
||||
|
||||
def yugioh06_difficulty(state: CollectionState, player: int, amount: int):
|
||||
return state.has_from_list(core_booster, player, amount)
|
|
@ -0,0 +1,264 @@
|
|||
from typing import Dict, List, NamedTuple, Optional, Union
|
||||
|
||||
from BaseClasses import MultiWorld
|
||||
from worlds.generic.Rules import CollectionRule
|
||||
|
||||
from worlds.yugioh06 import item_to_index, tier_1_opponents, yugioh06_difficulty
|
||||
from worlds.yugioh06.locations import special
|
||||
|
||||
|
||||
class OpponentData(NamedTuple):
|
||||
id: int
|
||||
name: str
|
||||
campaign_info: List[str]
|
||||
tier: int
|
||||
column: int
|
||||
card_id: int = 0
|
||||
deck_name_id: int = 0
|
||||
deck_file: str = ""
|
||||
difficulty: int = 1
|
||||
additional_info: List[str] = []
|
||||
|
||||
def tier(self, tier):
|
||||
self.tier = tier
|
||||
|
||||
def column(self, column):
|
||||
self.column = column
|
||||
|
||||
|
||||
challenge_opponents = [
|
||||
# Theme
|
||||
OpponentData(27, "Exarion Universe", [], 1, 1, 5452, 13001, "deck/theme_001.ydc\x00\x00\x00\x00", 0),
|
||||
OpponentData(28, "Stone Statue of the Aztecs", [], 4, 1, 4754, 13002, "deck/theme_002.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(29, "Raging Flame Sprite", [], 1, 1, 6189, 13003, "deck/theme_003.ydc\x00\x00\x00\x00", 0),
|
||||
OpponentData(30, "Princess Pikeru", [], 1, 1, 6605, 13004, "deck/theme_004.ydc\x00\x00\x00\x00", 0),
|
||||
OpponentData(31, "Princess Curran", ["Quick-Finish"], 1, 1, 6606, 13005, "deck/theme_005.ydc\x00\x00\x00\x00", 0,
|
||||
["Has Back-row removal"]),
|
||||
OpponentData(32, "Gearfried the Iron Knight", ["Quick-Finish"], 2, 1, 5059, 13006,
|
||||
"deck/theme_006.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(33, "Zaborg the Thunder Monarch", [], 3, 1, 5965, 13007, "deck/theme_007.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(34, "Kycoo the Ghost Destroyer", ["Quick-Finish"], 3, 1, 5248, 13008,
|
||||
"deck/theme_008.ydc\x00\x00\x00\x00"),
|
||||
OpponentData(35, "Penguin Soldier", ["Quick-Finish"], 1, 1, 4608, 13009, "deck/theme_009.ydc\x00\x00\x00\x00", 0),
|
||||
OpponentData(36, "Green Gadget", [], 5, 1, 6151, 13010, "deck/theme_010.ydc\x00\x00\x00\x00", 5),
|
||||
OpponentData(37, "Guardian Sphinx", ["Quick-Finish"], 3, 1, 5422, 13011, "deck/theme_011.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(38, "Cyber-Tech Alligator", [], 2, 1, 4790, 13012, "deck/theme_012.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(39, "UFOroid Fighter", [], 3, 1, 6395, 13013, "deck/theme_013.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(40, "Relinquished", [], 3, 1, 4737, 13014, "deck/theme_014.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(41, "Manticore of Darkness", [], 2, 1, 5881, 13015, "deck/theme_015.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(42, "Vampire Lord", [], 3, 1, 5410, 13016, "deck/theme_016.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(43, "Gigantes", ["Quick-Finish"], 3, 1, 5831, 13017, "deck/theme_017.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(44, "Insect Queen", ["Quick-Finish"], 2, 1, 4768, 13018, "deck/theme_018.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(45, "Second Goblin", ["Quick-Finish"], 1, 1, 5587, 13019, "deck/theme_019.ydc\x00\x00\x00\x00", 0),
|
||||
OpponentData(46, "Toon Summoned Skull", [], 4, 1, 4735, 13020, "deck/theme_020.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(47, "Iron Blacksmith Kotetsu", [], 2, 1, 5769, 13021, "deck/theme_021.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(48, "Magician of Faith", [], 1, 1, 4434, 13022, "deck/theme_022.ydc\x00\x00\x00\x00", 0),
|
||||
OpponentData(49, "Mask of Darkness", [], 1, 1, 4108, 13023, "deck/theme_023.ydc\x00\x00\x00\x00", 0),
|
||||
OpponentData(50, "Dark Ruler Vandalgyon", [], 3, 1, 6410, 13024, "deck/theme_024.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(51, "Aussa the Earth Charmer", ["Quick-Finish"], 2, 1, 6335, 13025,
|
||||
"deck/theme_025.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(52, "Exodia Necross", ["Quick-Finish"], 2, 1, 5701, 13026, "deck/theme_026.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(53, "Dark Necrofear", [], 3, 1, 5222, 13027, "deck/theme_027.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(54, "Demise, King of Armageddon", [], 4, 1, 6613, 13028, "deck/theme_028.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(55, "Yamata Dragon", [], 3, 1, 5377, 13029, "deck/theme_029.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(56, "Blue-Eyes Ultimate Dragon", [], 3, 1, 4386, 13030, "deck/theme_030.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(57, "Wave-Motion Cannon", [], 4, 1, 5614, 13031, "deck/theme_031.ydc\x00\x00\x00\x00", 3,
|
||||
["Has Back-row removal"]),
|
||||
# Unused opponent
|
||||
# OpponentData(58, "Yata-Garasu", [], 1, 1, 5375, 13032, "deck/theme_031.ydc\x00\x00\x00\x00"),
|
||||
# Unused opponent
|
||||
# OpponentData(59, "Makyura the Destructor", [], 1, 1, 5285, 13033, "deck/theme_031.ydc\x00\x00\x00\x00"),
|
||||
OpponentData(60, "Morphing Jar", [], 5, 1, 4597, 13034, "deck/theme_034.ydc\x00\x00\x00\x00", 4),
|
||||
OpponentData(61, "Spirit Reaper", [], 2, 1, 5526, 13035, "deck/theme_035.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(62, "Victory D.", [], 3, 1, 5868, 13036, "deck/theme_036.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(63, "VWXYZ-Dragon Catapult Cannon", ["Quick-Finish"], 3, 1, 6484, 13037,
|
||||
"deck/theme_037.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(64, "XYZ-Dragon Cannon", [], 2, 1, 5556, 13038, "deck/theme_038.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(65, "Uria, Lord of Searing Flames", [], 4, 1, 6563, 13039, "deck/theme_039.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(66, "Hamon, Lord of Striking Thunder", [], 4, 1, 6564, 13040, "deck/theme_040.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(67, "Raviel, Lord of Phantasms TD", [], 4, 1, 6565, 13041, "deck/theme_041.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(68, "Ojama Trio", [], 1, 1, 5738, 13042, "deck/theme_042.ydc\x00\x00\x00\x00", 0),
|
||||
OpponentData(69, "People Running About", ["Quick-Finish"], 1, 1, 5578, 13043, "deck/theme_043.ydc\x00\x00\x00\x00",
|
||||
0),
|
||||
OpponentData(70, "Cyber-Stein", [], 5, 1, 4426, 13044, "deck/theme_044.ydc\x00\x00\x00\x00", 4),
|
||||
OpponentData(71, "Winged Kuriboh LV10", [], 4, 1, 6406, 13045, "deck/theme_045.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(72, "Blue-Eyes Shining Dragon", [], 3, 1, 6082, 13046, "deck/theme_046.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(73, "Perfectly Ultimate Great Moth", ["Quick-Finish"], 3, 1, 4073, 13047,
|
||||
"deck/theme_047.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(74, "Gate Guardian", [], 4, 1, 4380, 13048, "deck/theme_048.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(75, "Valkyrion the Magna Warrior", [], 3, 1, 5002, 13049, "deck/theme_049.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(76, "Dark Sage", [], 4, 1, 5230, 13050, "deck/theme_050.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(77, "Don Zaloog", [], 4, 1, 5426, 13051, "deck/theme_051.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(78, "Blast Magician", ["Quick-Finish"], 2, 1, 6250, 13052, "deck/theme_052.ydc\x00\x00\x00\x00", 1),
|
||||
# Limited
|
||||
OpponentData(79, "Zombyra the Dark", [], 5, 1, 5245, 23000, "deck/limit_000.ydc\x00\x00\x00\x00", 5),
|
||||
OpponentData(80, "Goblin Attack Force", [], 4, 1, 5145, 23001, "deck/limit_001.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(81, "Giant Kozaky", [], 4, 1, 6420, 23002, "deck/limit_002.ydc\x00\x00\x00\x00", 4),
|
||||
OpponentData(82, "Big Shield Gardna", ["Quick-Finish"], 2, 1, 4764, 23003, "deck/limit_003.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(83, "Panther Warrior", [], 3, 1, 4751, 23004, "deck/limit_004.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(84, "Silent Magician LV4", ["Quick-Finish"], 2, 1, 6167, 23005, "deck/limit_005.ydc\x00\x00\x00\x00",
|
||||
1),
|
||||
OpponentData(85, "Summoned Skull", [], 4, 1, 4028, 23006, "deck/limit_006.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(86, "Ancient Gear Golem", [], 5, 1, 6315, 23007, "deck/limit_007.ydc\x00\x00\x00\x00", 5),
|
||||
OpponentData(87, "Chaos Sorcerer", [], 5, 1, 5833, 23008, "deck/limit_008.ydc\x00\x00\x00\x00", 5),
|
||||
OpponentData(88, "Breaker the Magical Warrior", [], 5, 1, 5655, 23009, "deck/limit_009.ydc\x00\x00\x00\x00", 4),
|
||||
OpponentData(89, "Dark Magician of Chaos", [], 4, 1, 5880, 23010, "deck/limit_010.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(90, "Stealth Bird", ["Quick-Finish"], 2, 1, 5882, 23011, "deck/limit_011.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(91, "Rapid-Fire Magician", ["Quick-Finish"], 2, 1, 6500, 23012, "deck/limit_012.ydc\x00\x00\x00\x00",
|
||||
1),
|
||||
OpponentData(92, "Morphing Jar #2", [], 5, 1, 4969, 23013, "deck/limit_013.ydc\x00\x00\x00\x00", 4),
|
||||
OpponentData(93, "Cyber Jar", [], 5, 1, 4913, 23014, "deck/limit_014.ydc\x00\x00\x00\x00", 4),
|
||||
# Unused/Broken
|
||||
# OpponentData(94, "Exodia the Forbidden One", [], 1, 1, 4027, 23015, "deck/limit_015.ydc\x00\x00\x00\x00"),
|
||||
OpponentData(94, "Dark Paladin", [], 4, 1, 5628, 23016, "deck/limit_016.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(95, "F.G.D.", [], 5, 1, 5502, 23017, "deck/limit_017.ydc\x00\x00\x00\x00", 4),
|
||||
OpponentData(96, "Blue-Eyes Toon Dragon", ["Quick-Finish"], 2, 1, 4773, 23018, "deck/limit_018.ydc\x00\x00\x00\x00",
|
||||
1),
|
||||
OpponentData(97, "Tsukuyomi", [], 3, 1, 5780, 23019, "deck/limit_019.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(98, "Silent Swordsman LV3", ["Quick-Finish"], 2, 1, 6162, 23020, "deck/limit_020.ydc\x00\x00\x00\x00",
|
||||
2),
|
||||
OpponentData(99, "Elemental Hero Flame Wingman", ["Quick-Finish"], 2, 1, 6344, 23021,
|
||||
"deck/limit_021.ydc\x00\x00\x00\x00", 0),
|
||||
OpponentData(100, "Armed Dragon LV7", ["Quick-Finish"], 2, 1, 6107, 23022, "deck/limit_022.ydc\x00\x00\x00\x00", 0),
|
||||
OpponentData(101, "Alkana Knight Joker", ["Quick-Finish"], 1, 1, 6454, 23023, "deck/limit_023.ydc\x00\x00\x00\x00",
|
||||
0),
|
||||
OpponentData(102, "Sorcerer of Dark Magic", [], 4, 1, 6086, 23024, "deck/limit_024.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(103, "Shinato, King of a Higher Plane", [], 4, 1, 5697, 23025, "deck/limit_025.ydc\x00\x00\x00\x00",
|
||||
3),
|
||||
OpponentData(104, "Ryu Kokki", [], 5, 1, 5902, 23026, "deck/limit_026.ydc\x00\x00\x00\x00", 4),
|
||||
OpponentData(105, "Cyber Dragon", [], 5, 1, 6390, 23027, "deck/limit_027.ydc\x00\x00\x00\x00", 4),
|
||||
OpponentData(106, "Dark Dreadroute", ["Quick-Finish"], 3, 1, 6405, 23028, "deck/limit_028.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(107, "Ultimate Insect LV7", ["Quick-Finish"], 3, 1, 6319, 23029, "deck/limit_029.ydc\x00\x00\x00\x00",
|
||||
2),
|
||||
OpponentData(108, "Thestalos the Firestorm Monarch", ["Quick-Finish"], 3, 1, 6190, 23030,
|
||||
"deck/limit_030.ydc\x00\x00\x00\x00"),
|
||||
OpponentData(109, "Master of Oz", ["Quick-Finish"], 3, 1, 6127, 23031, "deck/limit_031.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(110, "Orca Mega-Fortress of Darkness", ["Quick-Finish"], 3, 1, 5896, 23032,
|
||||
"deck/limit_032.ydc\x00\x00\x00\x00", 2),
|
||||
OpponentData(111, "Airknight Parshath", ["Quick-Finish"], 4, 1, 5023, 23033, "deck/limit_033.ydc\x00\x00\x00\x00",
|
||||
3),
|
||||
OpponentData(112, "Dark Scorpion Burglars", ["Quick-Finish"], 4, 1, 5425, 23034,
|
||||
"deck/limit_034.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(113, "Gilford the Lightning", [], 4, 1, 5451, 23035, "deck/limit_035.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(114, "Embodiment of Apophis", [], 2, 1, 5234, 23036, "deck/limit_036.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(115, "Great Maju Garzett", [], 5, 1, 5768, 23037, "deck/limit_037.ydc\x00\x00\x00\x00", 4),
|
||||
OpponentData(116, "Black Luster Soldier - Envoy of the Beginning", [], 5, 1, 5835, 23038,
|
||||
"deck/limit_038.ydc\x00\x00\x00\x00", 4),
|
||||
OpponentData(117, "Red-Eyes B. Dragon", [], 4, 1, 4088, 23039, "deck/limit_039.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(118, "Blue-Eyes White Dragon", [], 4, 1, 4007, 23040, "deck/limit_040.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(119, "Dark Magician", [], 4, 1, 4041, 23041, "deck/limit_041.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(0, "Starter", ["Quick-Finish"], 1, 1, 4064, 1510, "deck/SD0_STARTER.ydc\x00\x00", 0),
|
||||
OpponentData(10, "DRAGON'S ROAR", ["Quick-Finish"], 2, 1, 6292, 1511, "deck/SD1_DRAGON.ydc\x00\x00\x00", 1),
|
||||
OpponentData(11, "ZOMBIE MADNESS", ["Quick-Finish"], 2, 1, 6293, 1512, "deck/SD2_UNDEAD.ydc\x00\x00\x00", 1),
|
||||
OpponentData(12, "BLAZING DESTRUCTION", ["Quick-Finish"], 2, 1, 6368, 1513, "deck/SD3_FIRE.ydc\x00\x00\x00\x00\x00",
|
||||
1,
|
||||
["Has Back-row removal"]),
|
||||
OpponentData(13, "FURY FROM THE DEEP", [], 2, 1, 6376, 1514,
|
||||
"deck/SD4_UMI.ydc\x00\x00\x00\x00\x00\x00", 1, ["Has Back-row removal"]),
|
||||
OpponentData(15, "WARRIORS TRIUMPH", ["Quick-Finish"], 2, 1, 6456, 1515, "deck/SD5_SOLDIER.ydc\x00\x00", 1),
|
||||
OpponentData(16, "SPELLCASTERS JUDGEMENT", ["Quick-Finish"], 2, 1, 6530, 1516, "deck/SD6_MAGICIAN.ydc\x00", 1),
|
||||
OpponentData(17, "INVICIBLE FORTRESS", [], 2, 1, 6640, 1517, "deck/SD7_GANSEKI.ydc\x00\x00", 1),
|
||||
OpponentData(7, "Goblin King 2", ["Quick-Finish"], 3, 3, 5973, 8007, "deck/LV2_kingG2.ydc\x00\x00\x00", 2),
|
||||
]
|
||||
|
||||
|
||||
def get_opponents(multiworld: Optional[MultiWorld], player: Optional[int], randomize: bool = False) -> List[
|
||||
OpponentData]:
|
||||
opponents_table: List[OpponentData] = [
|
||||
# Tier 1
|
||||
OpponentData(0, "Kuriboh", [], 1, 1, 4064, 8000, "deck/LV1_kuriboh.ydc\x00\x00"),
|
||||
OpponentData(1, "Scapegoat", [], 1, 2, 4818, 8001, "deck/LV1_sukego.ydc\x00\x00\x00", 0,
|
||||
["Has Back-row removal"]),
|
||||
OpponentData(2, "Skull Servant", [], 1, 3, 4030, 8002, "deck/LV1_waito.ydc\x00\x00\x00\x00", 0,
|
||||
["Has Back-row removal"]),
|
||||
OpponentData(3, "Watapon", [], 1, 4, 6092, 8003, "deck/LV1_watapon.ydc\x00\x00", 0, ["Has Back-row removal"]),
|
||||
OpponentData(4, "White Magician Pikeru", [], 1, 5, 5975, 8004, "deck/LV1_pikeru.ydc\x00\x00\x00"),
|
||||
# Tier 2
|
||||
OpponentData(5, "Battery Man C", ["Quick-Finish"], 2, 1, 6428, 8005, "deck/LV2_denti.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(6, "Ojama Yellow", [], 2, 2, 5811, 8006, "deck/LV2_ojama.ydc\x00\x00\x00\x00", 1,
|
||||
["Has Back-row removal"]),
|
||||
OpponentData(7, "Goblin King", ["Quick-Finish"], 2, 3, 5973, 8007, "deck/LV2_kingG.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(8, "Des Frog", ["Quick-Finish"], 2, 4, 6424, 8008, "deck/LV2_kaeru.ydc\x00\x00\x00\x00", 1),
|
||||
OpponentData(9, "Water Dragon", ["Quick-Finish"], 2, 5, 6481, 8009, "deck/LV2_waterD.ydc\x00\x00\x00", 1),
|
||||
# Tier 3
|
||||
OpponentData(10, "Red-Eyes Darkness Dragon", ["Quick-Finish"], 3, 1, 6292, 8010, "deck/LV3_RedEyes.ydc\x00\x00",
|
||||
2),
|
||||
OpponentData(11, "Vampire Genesis", ["Quick-Finish"], 3, 2, 6293, 8011, "deck/LV3_vamp.ydc\x00\x00\x00\x00\x00",
|
||||
2),
|
||||
OpponentData(12, "Infernal Flame Emperor", [], 3, 3, 6368, 8012, "deck/LV3_flame.ydc\x00\x00\x00\x00", 2,
|
||||
["Has Back-row removal"]),
|
||||
OpponentData(13, "Ocean Dragon Lord - Neo-Daedalus", [], 3, 4, 6376, 8013, "deck/LV3_daidaros.ydc\x00", 2,
|
||||
["Has Back-row removal"]),
|
||||
OpponentData(14, "Helios Duo Megiste", ["Quick-Finish"], 3, 5, 6647, 8014, "deck/LV3_heriosu.ydc\x00\x00", 2),
|
||||
# Tier 4
|
||||
OpponentData(15, "Gilford the Legend", ["Quick-Finish"], 4, 1, 6456, 8015, "deck/LV4_gilfo.ydc\x00\x00\x00\x00",
|
||||
3),
|
||||
OpponentData(16, "Dark Eradicator Warlock", ["Quick-Finish"], 4, 2, 6530, 8016, "deck/LV4_kuromadou.ydc", 3),
|
||||
OpponentData(17, "Guardian Exode", [], 4, 3, 6640, 8017, "deck/LV4_exodo.ydc\x00\x00\x00\x00", 3),
|
||||
OpponentData(18, "Goldd, Wu-Lord of Dark World", ["Quick-Finish"], 4, 4, 6505, 8018, "deck/LV4_ankokukai.ydc",
|
||||
3),
|
||||
OpponentData(19, "Elemental Hero Erikshieler", ["Quick-Finish"], 4, 5, 6639, 8019,
|
||||
"deck/LV4_Ehero.ydc\x00\x00\x00\x00", 3),
|
||||
# Tier 5
|
||||
OpponentData(20, "Raviel, Lord of Phantasms", [], 5, 1, 6565, 8020, "deck/LV5_ravieru.ydc\x00\x00", 4),
|
||||
OpponentData(21, "Horus the Black Flame Dragon LV8", [], 5, 2, 6100, 8021, "deck/LV5_horus.ydc\x00\x00\x00\x00",
|
||||
4),
|
||||
OpponentData(22, "Stronghold", [], 5, 3, 6153, 8022, "deck/LV5_gadget.ydc\x00\x00\x00", 5),
|
||||
OpponentData(23, "Sacred Phoenix of Nephthys", [], 5, 4, 6236, 8023, "deck/LV5_nephthys.ydc\x00", 6),
|
||||
OpponentData(24, "Cyber End Dragon", ["Goal"], 5, 5, 6397, 8024, "deck/LV5_cyber.ydc\x00\x00\x00\x00", 7),
|
||||
]
|
||||
world = multiworld.worlds[player]
|
||||
if not randomize:
|
||||
return opponents_table
|
||||
opponents = opponents_table + challenge_opponents
|
||||
start = world.random.choice([o for o in opponents if o.tier == 1 and len(o.additional_info) == 0])
|
||||
opponents.remove(start)
|
||||
goal = world.random.choice([o for o in opponents if "Goal" in o.campaign_info])
|
||||
opponents.remove(goal)
|
||||
world.random.shuffle(opponents)
|
||||
chosen_ones = opponents[:23]
|
||||
for item in (multiworld.precollected_items[player]):
|
||||
if item.name in tier_1_opponents:
|
||||
# convert item index to opponent index
|
||||
chosen_ones.insert(item_to_index[item.name] - item_to_index["Campaign Tier 1 Column 1"], start)
|
||||
break
|
||||
chosen_ones.append(goal)
|
||||
tier = 1
|
||||
column = 1
|
||||
recreation = []
|
||||
for opp in chosen_ones:
|
||||
recreation.append(OpponentData(opp.id, opp.name, opp.campaign_info, tier, column, opp.card_id,
|
||||
opp.deck_name_id, opp.deck_file, opp.difficulty))
|
||||
column += 1
|
||||
if column > 5:
|
||||
column = 1
|
||||
tier += 1
|
||||
|
||||
return recreation
|
||||
|
||||
|
||||
def get_opponent_locations(opponent: OpponentData) -> Dict[str, Optional[Union[str, int]]]:
|
||||
location = {opponent.name + " Beaten": "Tier " + str(opponent.tier) + " Beaten"}
|
||||
if opponent.tier > 4 and opponent.column != 5:
|
||||
name = "Campaign Tier 5: Column " + str(opponent.column) + " Win"
|
||||
# return a int instead so a item can be placed at this location later
|
||||
location[name] = special[name]
|
||||
for info in opponent.campaign_info:
|
||||
location[opponent.name + "-> " + info] = info
|
||||
return location
|
||||
|
||||
|
||||
def get_opponent_condition(opponent: OpponentData, unlock_item: str, unlock_amount: int, player: int,
|
||||
is_challenge: bool) -> CollectionRule:
|
||||
if is_challenge:
|
||||
return lambda state: (
|
||||
state.has(unlock_item, player, unlock_amount)
|
||||
and yugioh06_difficulty(state, player, opponent.difficulty)
|
||||
and state.has_all(opponent.additional_info, player)
|
||||
)
|
||||
else:
|
||||
return lambda state: (
|
||||
state.has_group(unlock_item, player, unlock_amount)
|
||||
and yugioh06_difficulty(state, player, opponent.difficulty)
|
||||
and state.has_all(opponent.additional_info, player)
|
||||
)
|
|
@ -0,0 +1,195 @@
|
|||
from dataclasses import dataclass
|
||||
|
||||
from Options import Choice, DefaultOnToggle, PerGameCommonOptions, Range, Toggle
|
||||
|
||||
|
||||
class StructureDeck(Choice):
|
||||
"""Which Structure Deck you start with"""
|
||||
|
||||
display_name = "Structure Deck"
|
||||
option_dragons_roar = 0
|
||||
option_zombie_madness = 1
|
||||
option_blazing_destruction = 2
|
||||
option_fury_from_the_deep = 3
|
||||
option_warriors_triumph = 4
|
||||
option_spellcasters_judgement = 5
|
||||
option_none = 6
|
||||
option_random_deck = 7
|
||||
default = 7
|
||||
|
||||
|
||||
class Banlist(Choice):
|
||||
"""Which Banlist you start with"""
|
||||
|
||||
display_name = "Banlist"
|
||||
option_no_banlist = 0
|
||||
option_september_2003 = 1
|
||||
option_march_2004 = 2
|
||||
option_september_2004 = 3
|
||||
option_march_2005 = 4
|
||||
option_september_2005 = 5
|
||||
default = option_september_2005
|
||||
|
||||
|
||||
class FinalCampaignBossUnlockCondition(Choice):
|
||||
"""How to unlock the final campaign boss and goal for the world"""
|
||||
|
||||
display_name = "Final Campaign Boss unlock Condition"
|
||||
option_campaign_opponents = 0
|
||||
option_challenges = 1
|
||||
|
||||
|
||||
class FourthTier5UnlockCondition(Choice):
|
||||
"""How to unlock the fourth campaign boss"""
|
||||
|
||||
display_name = "Fourth Tier 5 Campaign Boss unlock Condition"
|
||||
option_campaign_opponents = 0
|
||||
option_challenges = 1
|
||||
|
||||
|
||||
class ThirdTier5UnlockCondition(Choice):
|
||||
"""How to unlock the third campaign boss"""
|
||||
|
||||
display_name = "Third Tier 5 Campaign Boss unlock Condition"
|
||||
option_campaign_opponents = 0
|
||||
option_challenges = 1
|
||||
|
||||
|
||||
class FinalCampaignBossChallenges(Range):
|
||||
"""Number of Limited/Theme Duels completed for the Final Campaign Boss to appear"""
|
||||
|
||||
display_name = "Final Campaign Boss challenges unlock amount"
|
||||
range_start = 0
|
||||
range_end = 91
|
||||
default = 10
|
||||
|
||||
|
||||
class FourthTier5CampaignBossChallenges(Range):
|
||||
"""Number of Limited/Theme Duels completed for the Fourth Level 5 Campaign Opponent to appear"""
|
||||
|
||||
display_name = "Fourth Tier 5 Campaign Boss unlock amount"
|
||||
range_start = 0
|
||||
range_end = 91
|
||||
default = 5
|
||||
|
||||
|
||||
class ThirdTier5CampaignBossChallenges(Range):
|
||||
"""Number of Limited/Theme Duels completed for the Third Level 5 Campaign Opponent to appear"""
|
||||
|
||||
display_name = "Third Tier 5 Campaign Boss unlock amount"
|
||||
range_start = 0
|
||||
range_end = 91
|
||||
default = 2
|
||||
|
||||
|
||||
class FinalCampaignBossCampaignOpponents(Range):
|
||||
"""Number of Campaign Opponents Duels defeated for the Final Campaign Boss to appear"""
|
||||
|
||||
display_name = "Final Campaign Boss campaign opponent unlock amount"
|
||||
range_start = 0
|
||||
range_end = 24
|
||||
default = 12
|
||||
|
||||
|
||||
class FourthTier5CampaignBossCampaignOpponents(Range):
|
||||
"""Number of Campaign Opponents Duels defeated for the Fourth Level 5 Campaign Opponent to appear"""
|
||||
|
||||
display_name = "Fourth Tier 5 Campaign Boss campaign opponent unlock amount"
|
||||
range_start = 0
|
||||
range_end = 23
|
||||
default = 7
|
||||
|
||||
|
||||
class ThirdTier5CampaignBossCampaignOpponents(Range):
|
||||
"""Number of Campaign Opponents Duels defeated for the Third Level 5 Campaign Opponent to appear"""
|
||||
|
||||
display_name = "Third Tier 5 Campaign Boss campaign opponent unlock amount"
|
||||
range_start = 0
|
||||
range_end = 22
|
||||
default = 3
|
||||
|
||||
|
||||
class NumberOfChallenges(Range):
|
||||
"""Number of random Limited/Theme Duels that are included. The rest will be inaccessible."""
|
||||
|
||||
display_name = "Number of Challenges"
|
||||
range_start = 0
|
||||
range_end = 91
|
||||
default = 10
|
||||
|
||||
|
||||
class StartingMoney(Range):
|
||||
"""The amount of money you start with"""
|
||||
|
||||
display_name = "Starting Money"
|
||||
range_start = 0
|
||||
range_end = 100000
|
||||
default = 3000
|
||||
|
||||
|
||||
class MoneyRewardMultiplier(Range):
|
||||
"""By which amount the campaign reward money is multiplied"""
|
||||
|
||||
display_name = "Money Reward Multiplier"
|
||||
range_start = 1
|
||||
range_end = 255
|
||||
default = 20
|
||||
|
||||
|
||||
class NormalizeBoostersPacks(DefaultOnToggle):
|
||||
"""If enabled every booster pack costs the same otherwise vanilla cost is used"""
|
||||
|
||||
display_name = "Normalize Booster Packs"
|
||||
|
||||
|
||||
class BoosterPackPrices(Range):
|
||||
"""
|
||||
Only Works if normalize booster packs is enabled.
|
||||
Sets the amount that what every booster pack costs.
|
||||
"""
|
||||
|
||||
display_name = "Booster Pack Prices"
|
||||
range_start = 1
|
||||
range_end = 3000
|
||||
default = 100
|
||||
|
||||
|
||||
class AddEmptyBanList(Toggle):
|
||||
"""Adds a Ban List where everything is at 3 to the item pool"""
|
||||
|
||||
display_name = "Add Empty Ban List"
|
||||
|
||||
|
||||
class CampaignOpponentsShuffle(Toggle):
|
||||
"""Replaces the campaign with random opponents from the entire game"""
|
||||
|
||||
display_name = "Campaign Opponents Shuffle"
|
||||
|
||||
|
||||
class OCGArts(Toggle):
|
||||
"""Always use the OCG artworks for cards"""
|
||||
|
||||
display_name = "OCG Arts"
|
||||
|
||||
|
||||
@dataclass
|
||||
class Yugioh06Options(PerGameCommonOptions):
|
||||
structure_deck: StructureDeck
|
||||
banlist: Banlist
|
||||
final_campaign_boss_unlock_condition: FinalCampaignBossUnlockCondition
|
||||
fourth_tier_5_campaign_boss_unlock_condition: FourthTier5UnlockCondition
|
||||
third_tier_5_campaign_boss_unlock_condition: ThirdTier5UnlockCondition
|
||||
final_campaign_boss_challenges: FinalCampaignBossChallenges
|
||||
fourth_tier_5_campaign_boss_challenges: FourthTier5CampaignBossChallenges
|
||||
third_tier_5_campaign_boss_challenges: ThirdTier5CampaignBossChallenges
|
||||
final_campaign_boss_campaign_opponents: FinalCampaignBossCampaignOpponents
|
||||
fourth_tier_5_campaign_boss_campaign_opponents: FourthTier5CampaignBossCampaignOpponents
|
||||
third_tier_5_campaign_boss_campaign_opponents: ThirdTier5CampaignBossCampaignOpponents
|
||||
number_of_challenges: NumberOfChallenges
|
||||
starting_money: StartingMoney
|
||||
money_reward_multiplier: MoneyRewardMultiplier
|
||||
normalize_boosters_packs: NormalizeBoostersPacks
|
||||
booster_pack_prices: BoosterPackPrices
|
||||
add_empty_banlist: AddEmptyBanList
|
||||
campaign_opponents_shuffle: CampaignOpponentsShuffle
|
||||
ocg_arts: OCGArts
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,163 @@
|
|||
import hashlib
|
||||
import math
|
||||
import os
|
||||
import struct
|
||||
|
||||
from settings import get_settings
|
||||
|
||||
import Utils
|
||||
from worlds.Files import APProcedurePatch, APTokenMixin, APTokenTypes
|
||||
|
||||
from worlds.AutoWorld import World
|
||||
from .items import item_to_index
|
||||
from .rom_values import banlist_ids, function_addresses, structure_deck_selection
|
||||
|
||||
MD5Europe = "020411d3b08f5639eb8cb878283f84bf"
|
||||
MD5America = "b8a7c976b28172995fe9e465d654297a"
|
||||
|
||||
|
||||
class YGO06ProcedurePatch(APProcedurePatch, APTokenMixin):
|
||||
game = "Yu-Gi-Oh! 2006"
|
||||
hash = MD5America
|
||||
patch_file_ending = ".apygo06"
|
||||
result_file_ending = ".gba"
|
||||
|
||||
procedure = [("apply_bsdiff4", ["base_patch.bsdiff4"]), ("apply_tokens", ["token_data.bin"])]
|
||||
|
||||
@classmethod
|
||||
def get_source_data(cls) -> bytes:
|
||||
return get_base_rom_bytes()
|
||||
|
||||
|
||||
def write_tokens(world: World, patch: YGO06ProcedurePatch):
|
||||
structure_deck = structure_deck_selection.get(world.options.structure_deck.value)
|
||||
# set structure deck
|
||||
patch.write_token(APTokenTypes.WRITE, 0x000FD0AA, struct.pack("<B", structure_deck))
|
||||
# set banlist
|
||||
banlist = world.options.banlist
|
||||
patch.write_token(APTokenTypes.WRITE, 0xF4496, struct.pack("<B", banlist_ids.get(banlist.value)))
|
||||
# set items to locations map
|
||||
randomizer_data_start = 0x0000F310
|
||||
for location in world.multiworld.get_locations(world.player):
|
||||
item = location.item.name
|
||||
if location.item.player != world.player:
|
||||
item = "Remote"
|
||||
item_id = item_to_index.get(item)
|
||||
if item_id is None:
|
||||
continue
|
||||
location_id = world.location_name_to_id[location.name] - 5730000
|
||||
patch.write_token(APTokenTypes.WRITE, randomizer_data_start + location_id, struct.pack("<B", item_id))
|
||||
# set starting inventory
|
||||
inventory_map = [0 for i in range(32)]
|
||||
starting_inventory = list(map(lambda i: i.name, world.multiworld.precollected_items[world.player]))
|
||||
starting_inventory += world.options.start_inventory.value
|
||||
for start_inventory in starting_inventory:
|
||||
item_id = world.item_name_to_id[start_inventory] - 5730001
|
||||
index = math.floor(item_id / 8)
|
||||
bit = item_id % 8
|
||||
inventory_map[index] = inventory_map[index] | (1 << bit)
|
||||
for i in range(32):
|
||||
patch.write_token(APTokenTypes.WRITE, 0xE9DC + i, struct.pack("<B", inventory_map[i]))
|
||||
# set unlock conditions for the last 3 campaign opponents
|
||||
third_tier_5 = (
|
||||
world.options.third_tier_5_campaign_boss_challenges.value
|
||||
if world.options.third_tier_5_campaign_boss_unlock_condition.value == 1
|
||||
else world.options.third_tier_5_campaign_boss_campaign_opponents.value
|
||||
)
|
||||
patch.write_token(APTokenTypes.WRITE, 0xEEFA, struct.pack("<B", third_tier_5))
|
||||
|
||||
fourth_tier_5 = (
|
||||
world.options.fourth_tier_5_campaign_boss_challenges.value
|
||||
if world.options.fourth_tier_5_campaign_boss_unlock_condition.value == 1
|
||||
else world.options.fourth_tier_5_campaign_boss_campaign_opponents.value
|
||||
)
|
||||
patch.write_token(APTokenTypes.WRITE, 0xEF10, struct.pack("<B", fourth_tier_5))
|
||||
final = (
|
||||
world.options.final_campaign_boss_challenges.value
|
||||
if world.options.final_campaign_boss_unlock_condition.value == 1
|
||||
else world.options.final_campaign_boss_campaign_opponents.value
|
||||
)
|
||||
patch.write_token(APTokenTypes.WRITE, 0xEF22, struct.pack("<B", final))
|
||||
|
||||
patch.write_token(
|
||||
APTokenTypes.WRITE,
|
||||
0xEEF8,
|
||||
struct.pack(
|
||||
"<B",
|
||||
int((function_addresses.get(world.options.third_tier_5_campaign_boss_unlock_condition.value) - 0xEEFA) / 2),
|
||||
),
|
||||
)
|
||||
patch.write_token(
|
||||
APTokenTypes.WRITE,
|
||||
0xEF0E,
|
||||
struct.pack(
|
||||
"<B",
|
||||
int(
|
||||
(function_addresses.get(world.options.fourth_tier_5_campaign_boss_unlock_condition.value) - 0xEF10) / 2
|
||||
),
|
||||
),
|
||||
)
|
||||
patch.write_token(
|
||||
APTokenTypes.WRITE,
|
||||
0xEF20,
|
||||
struct.pack(
|
||||
"<B", int((function_addresses.get(world.options.final_campaign_boss_unlock_condition.value) - 0xEF22) / 2)
|
||||
),
|
||||
)
|
||||
# set starting money
|
||||
patch.write_token(APTokenTypes.WRITE, 0xF4734, struct.pack("<I", world.options.starting_money))
|
||||
patch.write_token(APTokenTypes.WRITE, 0xE70C, struct.pack("<B", world.options.money_reward_multiplier.value))
|
||||
patch.write_token(APTokenTypes.WRITE, 0xE6E4, struct.pack("<B", world.options.money_reward_multiplier.value))
|
||||
# normalize booster packs if option is set
|
||||
if world.options.normalize_boosters_packs.value:
|
||||
booster_pack_price = world.options.booster_pack_prices.value.to_bytes(2, "little")
|
||||
for booster in range(51):
|
||||
space = booster * 16
|
||||
patch.write_token(APTokenTypes.WRITE, 0x1E5E2E8 + space, struct.pack("<B", booster_pack_price[0]))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x1E5E2E9 + space, struct.pack("<B", booster_pack_price[1]))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x1E5E2EA + space, struct.pack("<B", 5))
|
||||
# set shuffled campaign opponents if option is set
|
||||
if world.options.campaign_opponents_shuffle.value:
|
||||
i = 0
|
||||
for opp in world.campaign_opponents:
|
||||
space = i * 32
|
||||
patch.write_token(APTokenTypes.WRITE, 0x000F3BA + i, struct.pack("<B", opp.id))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x1E58D0E + space, struct.pack("<H", opp.card_id))
|
||||
patch.write_token(APTokenTypes.WRITE, 0x1E58D10 + space, struct.pack("<H", opp.deck_name_id))
|
||||
for j, b in enumerate(opp.deck_file.encode("ascii")):
|
||||
patch.write_token(APTokenTypes.WRITE, 0x1E58D12 + space + j, struct.pack("<B", b))
|
||||
i = i + 1
|
||||
|
||||
for j, b in enumerate(world.romName):
|
||||
patch.write_token(APTokenTypes.WRITE, 0x10 + j, struct.pack("<B", b))
|
||||
for j, b in enumerate(world.playerName):
|
||||
patch.write_token(APTokenTypes.WRITE, 0x30 + j, struct.pack("<B", b))
|
||||
|
||||
patch.write_file("token_data.bin", patch.get_token_binary())
|
||||
|
||||
|
||||
def get_base_rom_bytes(file_name: str = "") -> bytes:
|
||||
base_rom_bytes = getattr(get_base_rom_bytes, "base_rom_bytes", None)
|
||||
if not base_rom_bytes:
|
||||
file_name = get_base_rom_path(file_name)
|
||||
base_rom_bytes = bytes(Utils.read_snes_rom(open(file_name, "rb")))
|
||||
|
||||
basemd5 = hashlib.md5()
|
||||
basemd5.update(base_rom_bytes)
|
||||
md5hash = basemd5.hexdigest()
|
||||
if MD5Europe != md5hash and MD5America != md5hash:
|
||||
raise Exception(
|
||||
"Supplied Base Rom does not match known MD5 for"
|
||||
"Yu-Gi-Oh! World Championship 2006 America or Europe "
|
||||
"Get the correct game and version, then dump it"
|
||||
)
|
||||
get_base_rom_bytes.base_rom_bytes = base_rom_bytes
|
||||
return base_rom_bytes
|
||||
|
||||
|
||||
def get_base_rom_path(file_name: str = "") -> str:
|
||||
if not file_name:
|
||||
file_name = get_settings().yugioh06_settings.rom_file
|
||||
if not os.path.exists(file_name):
|
||||
file_name = Utils.user_path(file_name)
|
||||
return file_name
|
|
@ -0,0 +1,38 @@
|
|||
structure_deck_selection = {
|
||||
# DRAGON'S ROAR
|
||||
0: 0x1,
|
||||
# ZOMBIE MADNESS
|
||||
1: 0x5,
|
||||
# BLAZING DESTRUCTION
|
||||
2: 0x9,
|
||||
# FURY FROM THE DEEP
|
||||
3: 0xD,
|
||||
# Warrior'S TRIUMPH
|
||||
4: 0x11,
|
||||
# SPELLCASTER'S JUDGEMENT
|
||||
5: 0x15,
|
||||
# Draft Mode
|
||||
6: 0x1,
|
||||
}
|
||||
|
||||
banlist_ids = {
|
||||
# NoList
|
||||
0: 0x0,
|
||||
# September 2003
|
||||
1: 0x5,
|
||||
# March 2004
|
||||
2: 0x6,
|
||||
# September 2004
|
||||
3: 0x7,
|
||||
# March 2005
|
||||
4: 0x8,
|
||||
# September 2005
|
||||
5: 0x9,
|
||||
}
|
||||
|
||||
function_addresses = {
|
||||
# Count Campaign Opponents
|
||||
0: 0xF0C8,
|
||||
# Count Challenges
|
||||
1: 0xEF3A,
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
line-length = 120
|
||||
|
||||
[lint]
|
||||
preview = true
|
||||
select = ["E", "F", "W", "I", "N", "Q", "UP", "RUF", "ISC", "T20"]
|
||||
ignore = ["RUF012", "RUF100"]
|
||||
|
||||
[per-file-ignores]
|
||||
# The way options definitions work right now, world devs are forced to break line length requirements.
|
||||
"options.py" = ["E501"]
|
||||
# Yu Gi Oh specific: The structure of the Opponents.py file makes the line length violations acceptable.
|
||||
"Opponents.py" = ["E501"]
|
|
@ -0,0 +1,868 @@
|
|||
from worlds.generic.Rules import add_rule
|
||||
|
||||
from . import yugioh06_difficulty
|
||||
from .fusions import count_has_materials
|
||||
|
||||
|
||||
def set_rules(world):
|
||||
player = world.player
|
||||
multiworld = world.multiworld
|
||||
|
||||
location_rules = {
|
||||
# Campaign
|
||||
"Campaign Tier 1: 1 Win": lambda state: state.has("Tier 1 Beaten", player),
|
||||
"Campaign Tier 1: 3 Wins A": lambda state: state.has("Tier 1 Beaten", player, 3),
|
||||
"Campaign Tier 1: 3 Wins B": lambda state: state.has("Tier 1 Beaten", player, 3),
|
||||
"Campaign Tier 1: 5 Wins A": lambda state: state.has("Tier 1 Beaten", player, 5),
|
||||
"Campaign Tier 1: 5 Wins B": lambda state: state.has("Tier 1 Beaten", player, 5),
|
||||
"Campaign Tier 2: 1 Win": lambda state: state.has("Tier 2 Beaten", player),
|
||||
"Campaign Tier 2: 3 Wins A": lambda state: state.has("Tier 2 Beaten", player, 3),
|
||||
"Campaign Tier 2: 3 Wins B": lambda state: state.has("Tier 2 Beaten", player, 3),
|
||||
"Campaign Tier 2: 5 Wins A": lambda state: state.has("Tier 2 Beaten", player, 5),
|
||||
"Campaign Tier 2: 5 Wins B": lambda state: state.has("Tier 2 Beaten", player, 5),
|
||||
"Campaign Tier 3: 1 Win": lambda state: state.has("Tier 3 Beaten", player),
|
||||
"Campaign Tier 3: 3 Wins A": lambda state: state.has("Tier 3 Beaten", player, 3),
|
||||
"Campaign Tier 3: 3 Wins B": lambda state: state.has("Tier 3 Beaten", player, 3),
|
||||
"Campaign Tier 3: 5 Wins A": lambda state: state.has("Tier 3 Beaten", player, 5),
|
||||
"Campaign Tier 3: 5 Wins B": lambda state: state.has("Tier 3 Beaten", player, 5),
|
||||
"Campaign Tier 4: 5 Wins A": lambda state: state.has("Tier 4 Beaten", player, 5),
|
||||
"Campaign Tier 4: 5 Wins B": lambda state: state.has("Tier 4 Beaten", player, 5),
|
||||
|
||||
# Bonuses
|
||||
"Duelist Bonus Level 1": lambda state: state.has("Tier 1 Beaten", player),
|
||||
"Duelist Bonus Level 2": lambda state: state.has("Tier 2 Beaten", player),
|
||||
"Duelist Bonus Level 3": lambda state: state.has("Tier 3 Beaten", player),
|
||||
"Duelist Bonus Level 4": lambda state: state.has("Tier 4 Beaten", player),
|
||||
"Duelist Bonus Level 5": lambda state: state.has("Tier 5 Beaten", player),
|
||||
"Max ATK Bonus": lambda state: yugioh06_difficulty(state, player, 2),
|
||||
"No Spell Cards Bonus": lambda state: yugioh06_difficulty(state, player, 2),
|
||||
"No Trap Cards Bonus": lambda state: yugioh06_difficulty(state, player, 2),
|
||||
"No Damage Bonus": lambda state: state.has_group("Campaign Boss Beaten", player, 3),
|
||||
"Low Deck Bonus": lambda state: state.has_any(["Reasoning", "Monster Gate", "Magical Merchant"], player) and
|
||||
yugioh06_difficulty(state, player, 3),
|
||||
"Extremely Low Deck Bonus":
|
||||
lambda state: state.has_any(["Reasoning", "Monster Gate", "Magical Merchant"], player) and
|
||||
yugioh06_difficulty(state, player, 2),
|
||||
"Opponent's Turn Finish Bonus": lambda state: yugioh06_difficulty(state, player, 2),
|
||||
"Exactly 0 LP Bonus": lambda state: yugioh06_difficulty(state, player, 2),
|
||||
"Reversal Finish Bonus": lambda state: yugioh06_difficulty(state, player, 2),
|
||||
"Quick Finish Bonus": lambda state: state.has("Quick-Finish", player) or yugioh06_difficulty(state, player, 6),
|
||||
"Exodia Finish Bonus": lambda state: state.has("Can Exodia Win", player),
|
||||
"Last Turn Finish Bonus": lambda state: state.has("Can Last Turn Win", player),
|
||||
"Yata-Garasu Finish Bonus": lambda state: state.has("Can Yata Lock", player),
|
||||
"Skull Servant Finish Bonus": lambda state: state.has("Skull Servant", player) and
|
||||
yugioh06_difficulty(state, player, 3),
|
||||
"Konami Bonus": lambda state: state.has_all(["Messenger of Peace", "Castle of Dark Illusions", "Mystik Wok"],
|
||||
player) or (state.has_all(["Mystik Wok", "Barox", "Cyber-Stein",
|
||||
"Poison of the Old Man"],
|
||||
player) and yugioh06_difficulty(state,
|
||||
player, 8)),
|
||||
"Max Damage Bonus": lambda state: state.has_any(["Wave-Motion Cannon", "Megamorph", "United We Stand",
|
||||
"Mage Power"], player),
|
||||
"Fusion Summon Bonus": lambda state: state.has_any(["Polymerization", "Fusion Gate", "Power Bond"], player),
|
||||
"Ritual Summon Bonus": lambda state: state.has("Ritual", player),
|
||||
"Over 20000 LP Bonus": lambda state: can_gain_lp_every_turn(state, player)
|
||||
and state.has("Can Stall with ST", player),
|
||||
"Low LP Bonus": lambda state: state.has("Wall of Revealing Light", player) and yugioh06_difficulty(state, player,
|
||||
2),
|
||||
"Extremely Low LP Bonus": lambda state: state.has_all(["Wall of Revealing Light", "Messenger of Peace"], player)
|
||||
and yugioh06_difficulty(state, player, 4),
|
||||
"Effect Damage Only Bonus": lambda state: state.has_all(["Solar Flare Dragon", "UFO Turtle"], player)
|
||||
or state.has("Wave-Motion Cannon", player)
|
||||
or state.can_reach("Final Countdown Finish Bonus", "Location", player)
|
||||
or state.can_reach("Destiny Board Finish Bonus", "Location", player)
|
||||
or state.has("Can Exodia Win", player)
|
||||
or state.has("Can Last Turn Win", player),
|
||||
"No More Cards Bonus": lambda state: state.has_any(["Cyber Jar", "Morphing Jar",
|
||||
"Morphing Jar #2", "Needle Worm"], player)
|
||||
and state.has_any(["The Shallow Grave", "Spear Cretin"],
|
||||
player) and yugioh06_difficulty(state, player, 5),
|
||||
"Final Countdown Finish Bonus": lambda state: state.has("Final Countdown", player)
|
||||
and state.has("Can Stall with ST", player),
|
||||
"Destiny Board Finish Bonus": lambda state: state.has("Can Stall with Monsters", player) and
|
||||
state.has("Destiny Board and its letters", player) and
|
||||
state.has("A Cat of Ill Omen", player),
|
||||
|
||||
# Cards
|
||||
"Obtain all pieces of Exodia": lambda state: state.has("Exodia", player),
|
||||
"Obtain Final Countdown": lambda state: state.has("Final Countdown", player),
|
||||
"Obtain Victory Dragon": lambda state: state.has("Victory D.", player),
|
||||
"Obtain Ojama Delta Hurricane and its required cards":
|
||||
lambda state: state.has("Ojama Delta Hurricane and required cards", player),
|
||||
"Obtain Huge Revolution and its required cards":
|
||||
lambda state: state.has("Huge Revolution and its required cards", player),
|
||||
"Obtain Perfectly Ultimate Great Moth and its required cards":
|
||||
lambda state: state.has("Perfectly Ultimate Great Moth and its required cards", player),
|
||||
"Obtain Valkyrion the Magna Warrior and its pieces":
|
||||
lambda state: state.has("Valkyrion the Magna Warrior and its pieces", player),
|
||||
"Obtain Dark Sage and its required cards": lambda state: state.has("Dark Sage and its required cards", player),
|
||||
"Obtain Destiny Board and its letters": lambda state: state.has("Destiny Board and its letters", player),
|
||||
"Obtain all XYZ-Dragon Cannon fusions and their materials":
|
||||
lambda state: state.has("XYZ-Dragon Cannon fusions and their materials", player),
|
||||
"Obtain VWXYZ-Dragon Catapult Cannon and the fusion materials":
|
||||
lambda state: state.has("VWXYZ-Dragon Catapult Cannon and the fusion materials", player),
|
||||
"Obtain Hamon, Lord of Striking Thunder":
|
||||
lambda state: state.has("Hamon, Lord of Striking Thunder", player),
|
||||
"Obtain Raviel, Lord of Phantasms":
|
||||
lambda state: state.has("Raviel, Lord of Phantasms", player),
|
||||
"Obtain Uria, Lord of Searing Flames":
|
||||
lambda state: state.has("Uria, Lord of Searing Flames", player),
|
||||
"Obtain Gate Guardian and its pieces":
|
||||
lambda state: state.has("Gate Guardian and its pieces", player),
|
||||
"Obtain Dark Scorpion Combination and its required cards":
|
||||
lambda state: state.has("Dark Scorpion Combination and its required cards", player),
|
||||
# Collection Events
|
||||
"Ojama Delta Hurricane and required cards":
|
||||
lambda state: state.has_all(["Ojama Delta Hurricane", "Ojama Green", "Ojama Yellow", "Ojama Black"],
|
||||
player),
|
||||
"Huge Revolution and its required cards":
|
||||
lambda state: state.has_all(["Huge Revolution", "Oppressed People", "United Resistance",
|
||||
"People Running About"], player),
|
||||
"Perfectly Ultimate Great Moth and its required cards":
|
||||
lambda state: state.has_all(["Perfectly Ultimate Great Moth", "Petit Moth", "Cocoon of Evolution"], player),
|
||||
"Valkyrion the Magna Warrior and its pieces":
|
||||
lambda state: state.has_all(["Valkyrion the Magna Warrior", "Alpha the Magnet Warrior",
|
||||
"Beta the Magnet Warrior", "Gamma the Magnet Warrior"], player),
|
||||
"Dark Sage and its required cards":
|
||||
lambda state: state.has_all(["Dark Sage", "Dark Magician", "Time Wizard"], player),
|
||||
"Destiny Board and its letters":
|
||||
lambda state: state.has_all(["Destiny Board", "Spirit Message 'I'", "Spirit Message 'N'",
|
||||
"Spirit Message 'A'", "Spirit Message 'L'"], player),
|
||||
"XYZ-Dragon Cannon fusions and their materials":
|
||||
lambda state: state.has_all(["X-Head Cannon", "Y-Dragon Head", "Z-Metal Tank",
|
||||
"XY-Dragon Cannon", "XZ-Tank Cannon", "YZ-Tank Dragon", "XYZ-Dragon Cannon"],
|
||||
player),
|
||||
"VWXYZ-Dragon Catapult Cannon and the fusion materials":
|
||||
lambda state: state.has_all(["X-Head Cannon", "Y-Dragon Head", "Z-Metal Tank", "XYZ-Dragon Cannon",
|
||||
"V-Tiger Jet", "W-Wing Catapult", "VW-Tiger Catapult",
|
||||
"VWXYZ-Dragon Catapult Cannon"],
|
||||
player),
|
||||
"Gate Guardian and its pieces":
|
||||
lambda state: state.has_all(["Gate Guardian", "Kazejin", "Suijin", "Sanga of the Thunder"], player),
|
||||
"Dark Scorpion Combination and its required cards":
|
||||
lambda state: state.has_all(["Dark Scorpion Combination", "Don Zaloog", "Dark Scorpion - Chick the Yellow",
|
||||
"Dark Scorpion - Meanae the Thorn", "Dark Scorpion - Gorg the Strong",
|
||||
"Cliff the Trap Remover"], player),
|
||||
"Can Exodia Win":
|
||||
lambda state: state.has_all(["Exodia", "Heart of the Underdog"], player),
|
||||
"Can Last Turn Win":
|
||||
lambda state: state.has_all(["Last Turn", "Wall of Revealing Light"], player) and
|
||||
(state.has_any(["Jowgen the Spiritualist", "Jowls of Dark Demise", "Non Aggression Area"],
|
||||
player)
|
||||
or state.has_all(["Cyber-Stein", "The Last Warrior from Another Planet"], player)),
|
||||
"Can Yata Lock":
|
||||
lambda state: state.has_all(["Yata-Garasu", "Chaos Emperor Dragon - Envoy of the End", "Sangan"], player)
|
||||
and state.has_any(["No Banlist", "Banlist September 2003"], player),
|
||||
"Can Stall with Monsters":
|
||||
lambda state: state.count_from_list_exclusive(
|
||||
["Spirit Reaper", "Giant Germ", "Marshmallon", "Nimble Momonga"], player) >= 2,
|
||||
"Can Stall with ST":
|
||||
lambda state: state.count_from_list_exclusive(["Level Limit - Area B", "Gravity Bind", "Messenger of Peace"],
|
||||
player) >= 2,
|
||||
"Has Back-row removal":
|
||||
lambda state: back_row_removal(state, player)
|
||||
|
||||
}
|
||||
access_rules = {
|
||||
# Limited
|
||||
"LD01 All except Level 4 forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 2),
|
||||
"LD02 Medium/high Level forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 1),
|
||||
"LD03 ATK 1500 or more forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 4),
|
||||
"LD04 Flip Effects forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 1),
|
||||
"LD05 Tributes forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 1),
|
||||
"LD06 Traps forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 1),
|
||||
"LD07 Large Deck A":
|
||||
lambda state: yugioh06_difficulty(state, player, 4),
|
||||
"LD08 Large Deck B":
|
||||
lambda state: yugioh06_difficulty(state, player, 4),
|
||||
"LD09 Sets Forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 1),
|
||||
"LD10 All except LV monsters forbidden":
|
||||
lambda state: only_level(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD11 All except Fairies forbidden":
|
||||
lambda state: only_fairy(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD12 All except Wind forbidden":
|
||||
lambda state: only_wind(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD13 All except monsters forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 3),
|
||||
"LD14 Level 3 or below forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 1),
|
||||
"LD15 DEF 1500 or less forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 3),
|
||||
"LD16 Effect Monsters forbidden":
|
||||
lambda state: only_normal(state, player) and yugioh06_difficulty(state, player, 4),
|
||||
"LD17 Spells forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 3),
|
||||
"LD18 Attacks forbidden":
|
||||
lambda state: state.has_all(["Wave-Motion Cannon", "Stealth Bird"], player)
|
||||
and state.count_from_list_exclusive(["Dark World Lightning", "Nobleman of Crossout",
|
||||
"Shield Crash", "Tribute to the Doomed"], player) >= 2
|
||||
and yugioh06_difficulty(state, player, 3),
|
||||
"LD19 All except E-Hero's forbidden":
|
||||
lambda state: state.has_any(["Polymerization", "Fusion Gate"], player) and
|
||||
count_has_materials(state, ["Elemental Hero Flame Wingman",
|
||||
"Elemental Hero Madballman",
|
||||
"Elemental Hero Rampart Blaster",
|
||||
"Elemental Hero Steam Healer",
|
||||
"Elemental Hero Shining Flare Wingman",
|
||||
"Elemental Hero Wildedge"], player) >= 3 and
|
||||
yugioh06_difficulty(state, player, 3),
|
||||
"LD20 All except Warriors forbidden":
|
||||
lambda state: only_warrior(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD21 All except Dark forbidden":
|
||||
lambda state: only_dark(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD22 All limited cards forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 3),
|
||||
"LD23 Refer to Mar 05 Banlist":
|
||||
lambda state: yugioh06_difficulty(state, player, 5),
|
||||
"LD24 Refer to Sept 04 Banlist":
|
||||
lambda state: yugioh06_difficulty(state, player, 5),
|
||||
"LD25 Low Life Points":
|
||||
lambda state: yugioh06_difficulty(state, player, 5),
|
||||
"LD26 All except Toons forbidden":
|
||||
lambda state: only_toons(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD27 All except Spirits forbidden":
|
||||
lambda state: only_spirit(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD28 All except Dragons forbidden":
|
||||
lambda state: only_dragon(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD29 All except Spellcasters forbidden":
|
||||
lambda state: only_spellcaster(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD30 All except Light forbidden":
|
||||
lambda state: only_light(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD31 All except Fire forbidden":
|
||||
lambda state: only_fire(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD32 Decks with multiples forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 4),
|
||||
"LD33 Special Summons forbidden":
|
||||
lambda state: yugioh06_difficulty(state, player, 2),
|
||||
"LD34 Normal Summons forbidden":
|
||||
lambda state: state.has_all(["Polymerization", "King of the Swamp"], player) and
|
||||
count_has_materials(state, ["Elemental Hero Flame Wingman",
|
||||
"Elemental Hero Madballman",
|
||||
"Elemental Hero Rampart Blaster",
|
||||
"Elemental Hero Steam Healer",
|
||||
"Elemental Hero Shining Flare Wingman",
|
||||
"Elemental Hero Wildedge"], player) >= 3 and
|
||||
yugioh06_difficulty(state, player, 4),
|
||||
"LD35 All except Zombies forbidden":
|
||||
lambda state: only_zombie(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD36 All except Earth forbidden":
|
||||
lambda state: only_earth(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD37 All except Water forbidden":
|
||||
lambda state: only_water(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"LD38 Refer to Mar 04 Banlist":
|
||||
lambda state: yugioh06_difficulty(state, player, 4),
|
||||
"LD39 Monsters forbidden":
|
||||
lambda state: state.has_all(["Skull Zoma", "Embodiment of Apophis"], player)
|
||||
and yugioh06_difficulty(state, player, 5),
|
||||
"LD40 Refer to Sept 05 Banlist":
|
||||
lambda state: yugioh06_difficulty(state, player, 5),
|
||||
"LD41 Refer to Sept 03 Banlist":
|
||||
lambda state: yugioh06_difficulty(state, player, 5),
|
||||
# Theme Duels
|
||||
"TD01 Battle Damage":
|
||||
lambda state: yugioh06_difficulty(state, player, 1),
|
||||
"TD02 Deflected Damage":
|
||||
lambda state: state.has("Fairy Box", player) and yugioh06_difficulty(state, player, 1),
|
||||
"TD03 Normal Summon":
|
||||
lambda state: yugioh06_difficulty(state, player, 3),
|
||||
"TD04 Ritual Summon":
|
||||
lambda state: yugioh06_difficulty(state, player, 3) and
|
||||
state.has_all(["Contract with the Abyss",
|
||||
"Manju of the Ten Thousand Hands",
|
||||
"Senju of the Thousand Hands",
|
||||
"Sonic Bird",
|
||||
"Pot of Avarice",
|
||||
"Dark Master - Zorc",
|
||||
"Demise, King of Armageddon",
|
||||
"The Masked Beast",
|
||||
"Magician of Black Chaos",
|
||||
"Dark Magic Ritual"], player),
|
||||
"TD05 Special Summon A":
|
||||
lambda state: yugioh06_difficulty(state, player, 3),
|
||||
"TD06 20x Spell":
|
||||
lambda state: state.has("Magical Blast", player) and yugioh06_difficulty(state, player, 3),
|
||||
"TD07 10x Trap":
|
||||
lambda state: yugioh06_difficulty(state, player, 3),
|
||||
"TD08 Draw":
|
||||
lambda state: state.has_any(["Self-Destruct Button", "Dark Snake Syndrome"], player) and
|
||||
yugioh06_difficulty(state, player, 3),
|
||||
"TD09 Hand Destruction":
|
||||
lambda state: state.has_all(["Cyber Jar",
|
||||
"Morphing Jar",
|
||||
"Book of Moon",
|
||||
"Book of Taiyou",
|
||||
"Card Destruction",
|
||||
"Serial Spell",
|
||||
"Spell Reproduction",
|
||||
"The Shallow Grave"], player) and yugioh06_difficulty(state, player, 3),
|
||||
"TD10 During Opponent's Turn":
|
||||
lambda state: yugioh06_difficulty(state, player, 3),
|
||||
"TD11 Recover":
|
||||
lambda state: can_gain_lp_every_turn(state, player) and yugioh06_difficulty(state, player, 3),
|
||||
"TD12 Remove Monsters by Effect":
|
||||
lambda state: state.has("Soul Release", player) and yugioh06_difficulty(state, player, 2),
|
||||
"TD13 Flip Summon":
|
||||
lambda state: pacman_deck(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"TD14 Special Summon B":
|
||||
lambda state: state.has_any(["Manticore of Darkness", "Treeborn Frog"], player) and
|
||||
state.has("Foolish Burial", player) and
|
||||
yugioh06_difficulty(state, player, 2),
|
||||
"TD15 Token":
|
||||
lambda state: state.has_all(["Dandylion", "Ojama Trio", "Stray Lambs"], player) and
|
||||
yugioh06_difficulty(state, player, 3),
|
||||
"TD16 Union":
|
||||
lambda state: equip_unions(state, player) and
|
||||
yugioh06_difficulty(state, player, 2),
|
||||
"TD17 10x Quick Spell":
|
||||
lambda state: quick_plays(state, player) and
|
||||
yugioh06_difficulty(state, player, 3),
|
||||
"TD18 The Forbidden":
|
||||
lambda state: state.has("Can Exodia Win", player),
|
||||
"TD19 20 Turns":
|
||||
lambda state: state.has("Final Countdown", player) and state.has("Can Stall with ST", player) and
|
||||
yugioh06_difficulty(state, player, 3),
|
||||
"TD20 Deck Destruction":
|
||||
lambda state: state.has_any(["Cyber Jar", "Morphing Jar", "Morphing Jar #2", "Needle Worm"], player)
|
||||
and state.has_any(["The Shallow Grave", "Spear Cretin"],
|
||||
player) and yugioh06_difficulty(state, player, 2),
|
||||
"TD21 Victory D.":
|
||||
lambda state: state.has("Victory D.", player) and only_dragon(state, player)
|
||||
and yugioh06_difficulty(state, player, 3),
|
||||
"TD22 The Preventers Fight Back":
|
||||
lambda state: state.has("Ojama Delta Hurricane and required cards", player) and
|
||||
state.has_all(["Rescue Cat", "Enchanting Fitting Room", "Jerry Beans Man"], player) and
|
||||
yugioh06_difficulty(state, player, 3),
|
||||
"TD23 Huge Revolution":
|
||||
lambda state: state.has("Huge Revolution and its required cards", player) and
|
||||
state.has_all(["Enchanting Fitting Room", "Jerry Beans Man"], player) and
|
||||
yugioh06_difficulty(state, player, 3),
|
||||
"TD24 Victory in 5 Turns":
|
||||
lambda state: yugioh06_difficulty(state, player, 3),
|
||||
"TD25 Moth Grows Up":
|
||||
lambda state: state.has("Perfectly Ultimate Great Moth and its required cards", player) and
|
||||
state.has_all(["Gokipon", "Howling Insect"], player) and
|
||||
yugioh06_difficulty(state, player, 3),
|
||||
"TD26 Magnetic Power":
|
||||
lambda state: state.has("Valkyrion the Magna Warrior and its pieces", player) and
|
||||
yugioh06_difficulty(state, player, 2),
|
||||
"TD27 Dark Sage":
|
||||
lambda state: state.has("Dark Sage and its required cards", player) and
|
||||
state.has_any(["Skilled Dark Magician", "Dark Magic Curtain"], player) and
|
||||
yugioh06_difficulty(state, player, 2),
|
||||
"TD28 Direct Damage":
|
||||
lambda state: yugioh06_difficulty(state, player, 2),
|
||||
"TD29 Destroy Monsters in Battle":
|
||||
lambda state: yugioh06_difficulty(state, player, 2),
|
||||
"TD30 Tribute Summon":
|
||||
lambda state: state.has("Treeborn Frog", player) and yugioh06_difficulty(state, player, 2),
|
||||
"TD31 Special Summon C":
|
||||
lambda state: state.count_from_list_exclusive(
|
||||
["Aqua Spirit", "Rock Spirit", "Spirit of Flames",
|
||||
"Garuda the Wind Spirit", "Gigantes", "Inferno", "Megarock Dragon", "Silpheed"],
|
||||
player) > 4 and yugioh06_difficulty(state, player, 3),
|
||||
"TD32 Toon":
|
||||
lambda state: only_toons(state, player) and yugioh06_difficulty(state, player, 3),
|
||||
"TD33 10x Counter":
|
||||
lambda state: counter_traps(state, player) and yugioh06_difficulty(state, player, 2),
|
||||
"TD34 Destiny Board":
|
||||
lambda state: state.has("Destiny Board and its letters", player)
|
||||
and state.has("Can Stall with Monsters", player)
|
||||
and state.has("A Cat of Ill Omen", player)
|
||||
and yugioh06_difficulty(state, player, 2),
|
||||
"TD35 Huge Damage in a Turn":
|
||||
lambda state: state.has_all(["Cyber-Stein", "Cyber Twin Dragon", "Megamorph"], player)
|
||||
and yugioh06_difficulty(state, player, 3),
|
||||
"TD36 V-Z In the House":
|
||||
lambda state: state.has("VWXYZ-Dragon Catapult Cannon and the fusion materials", player)
|
||||
and yugioh06_difficulty(state, player, 3),
|
||||
"TD37 Uria, Lord of Searing Flames":
|
||||
lambda state: state.has_all(["Uria, Lord of Searing Flames",
|
||||
"Embodiment of Apophis",
|
||||
"Skull Zoma",
|
||||
"Metal Reflect Slime"], player)
|
||||
and yugioh06_difficulty(state, player, 3),
|
||||
"TD38 Hamon, Lord of Striking Thunder":
|
||||
lambda state: state.has("Hamon, Lord of Striking Thunder", player)
|
||||
and yugioh06_difficulty(state, player, 3),
|
||||
"TD39 Raviel, Lord of Phantasms":
|
||||
lambda state: state.has_all(["Raviel, Lord of Phantasms", "Giant Germ"], player) and
|
||||
state.count_from_list_exclusive(["Archfiend Soldier",
|
||||
"Skull Descovery Knight",
|
||||
"Slate Warrior",
|
||||
"D. D. Trainer",
|
||||
"Earthbound Spirit"], player) >= 3
|
||||
and yugioh06_difficulty(state, player, 3),
|
||||
"TD40 Make a Chain":
|
||||
lambda state: state.has("Ultimate Offering", player)
|
||||
and yugioh06_difficulty(state, player, 4),
|
||||
"TD41 The Gatekeeper Stands Tall":
|
||||
lambda state: state.has("Gate Guardian and its pieces", player) and
|
||||
state.has_all(["Treeborn Frog", "Tribute Doll"], player)
|
||||
and yugioh06_difficulty(state, player, 4),
|
||||
"TD42 Serious Damage":
|
||||
lambda state: yugioh06_difficulty(state, player, 3),
|
||||
"TD43 Return Monsters with Effects":
|
||||
lambda state: state.has_all(["Penguin Soldier", "Messenger of Peace"], player)
|
||||
and yugioh06_difficulty(state, player, 4),
|
||||
"TD44 Fusion Summon":
|
||||
lambda state: state.has_all(["Fusion Gate", "Terraforming", "Dimension Fusion",
|
||||
"Return from the Different Dimension"], player) and
|
||||
count_has_materials(state, ["Elemental Hero Flame Wingman",
|
||||
"Elemental Hero Madballman",
|
||||
"Elemental Hero Rampart Blaster",
|
||||
"Elemental Hero Steam Healer",
|
||||
"Elemental Hero Shining Flare Wingman",
|
||||
"Elemental Hero Wildedge"], player) >= 4 and
|
||||
yugioh06_difficulty(state, player, 7),
|
||||
"TD45 Big Damage at once":
|
||||
lambda state: state.has("Wave-Motion Cannon", player)
|
||||
and yugioh06_difficulty(state, player, 3),
|
||||
"TD46 XYZ In the House":
|
||||
lambda state: state.has("XYZ-Dragon Cannon fusions and their materials", player) and
|
||||
state.has("Dimension Fusion", player),
|
||||
"TD47 Spell Counter":
|
||||
lambda state: spell_counter(state, player) and yugioh06_difficulty(state, player, 3),
|
||||
"TD48 Destroy Monsters with Effects":
|
||||
lambda state: state.has_all(["Blade Rabbit", "Dream Clown"], player) and
|
||||
state.has("Can Stall with ST", player) and
|
||||
yugioh06_difficulty(state, player, 3),
|
||||
"TD49 Plunder":
|
||||
lambda state: take_control(state, player) and yugioh06_difficulty(state, player, 5),
|
||||
"TD50 Dark Scorpion Combination":
|
||||
lambda state: state.has("Dark Scorpion Combination and its required cards", player) and
|
||||
state.has_all(["Reinforcement of the Army", "Mystic Tomato"], player) and
|
||||
yugioh06_difficulty(state, player, 3)
|
||||
}
|
||||
multiworld.completion_condition[player] = lambda state: state.has("Goal", player)
|
||||
|
||||
for loc in multiworld.get_locations(player):
|
||||
if loc.name in location_rules:
|
||||
add_rule(loc, location_rules[loc.name])
|
||||
if loc.name in access_rules:
|
||||
add_rule(multiworld.get_entrance(loc.name, player), access_rules[loc.name])
|
||||
|
||||
|
||||
def only_light(state, player):
|
||||
return state.has_from_list_exclusive([
|
||||
"Dunames Dark Witch",
|
||||
"X-Head Cannon",
|
||||
"Homunculus the Alchemic Being",
|
||||
"Hysteric Fairy",
|
||||
"Ninja Grandmaster Sasuke"], player, 2)\
|
||||
and state.has_from_list_exclusive([
|
||||
"Chaos Command Magician",
|
||||
"Cybernetic Magician",
|
||||
"Kaiser Glider",
|
||||
"The Agent of Judgment - Saturn",
|
||||
"Zaborg the Thunder Monarch",
|
||||
"Cyber Dragon"], player, 1) \
|
||||
and state.has_from_list_exclusive([
|
||||
"D.D. Warrior Lady",
|
||||
"Mystic Swordsman LV2",
|
||||
"Y-Dragon Head",
|
||||
"Z-Metal Tank",
|
||||
], player, 2) and state.has("Shining Angel", player)
|
||||
|
||||
|
||||
def only_dark(state, player):
|
||||
return state.has_from_list_exclusive([
|
||||
"Dark Elf",
|
||||
"Archfiend Soldier",
|
||||
"Mad Dog of Darkness",
|
||||
"Vorse Raider",
|
||||
"Skilled Dark Magician",
|
||||
"Skull Descovery Knight",
|
||||
"Mechanicalchaser",
|
||||
"Dark Blade",
|
||||
"Gil Garth",
|
||||
"La Jinn the Mystical Genie of the Lamp",
|
||||
"Opticlops",
|
||||
"Zure, Knight of Dark World",
|
||||
"Brron, Mad King of Dark World",
|
||||
"D.D. Survivor",
|
||||
"Exarion Universe",
|
||||
"Kycoo the Ghost Destroyer",
|
||||
"Regenerating Mummy"
|
||||
], player, 2) \
|
||||
and state.has_any([
|
||||
"Summoned Skull",
|
||||
"Skull Archfiend of Lightning",
|
||||
"The End of Anubis",
|
||||
"Dark Ruler Ha Des",
|
||||
"Beast of Talwar",
|
||||
"Inferno Hammer",
|
||||
"Jinzo",
|
||||
"Ryu Kokki"
|
||||
], player) \
|
||||
and state.has_from_list_exclusive([
|
||||
"Legendary Fiend",
|
||||
"Don Zaloog",
|
||||
"Newdoria",
|
||||
"Sangan",
|
||||
"Spirit Reaper",
|
||||
"Giant Germ"
|
||||
], player, 2) and state.has("Mystic Tomato", player)
|
||||
|
||||
|
||||
def only_earth(state, player):
|
||||
return state.has_from_list_exclusive([
|
||||
"Berserk Gorilla",
|
||||
"Gemini Elf",
|
||||
"Insect Knight",
|
||||
"Toon Gemini Elf",
|
||||
"Familiar-Possessed - Aussa",
|
||||
"Neo Bug",
|
||||
"Blindly Loyal Goblin",
|
||||
"Chiron the Mage",
|
||||
"Gearfried the Iron Knight"
|
||||
], player, 2) and state.has_any([
|
||||
"Dark Driceratops",
|
||||
"Granmarg the Rock Monarch",
|
||||
"Hieracosphinx",
|
||||
"Saber Beetle"
|
||||
], player) and state.has_from_list_exclusive([
|
||||
"Hyper Hammerhead",
|
||||
"Green Gadget",
|
||||
"Red Gadget",
|
||||
"Yellow Gadget",
|
||||
"Dimensional Warrior",
|
||||
"Enraged Muka Muka",
|
||||
"Exiled Force"
|
||||
], player, 2) and state.has("Giant Rat", player)
|
||||
|
||||
|
||||
def only_water(state, player):
|
||||
return state.has_from_list_exclusive([
|
||||
"Gagagigo",
|
||||
"Familiar-Possessed - Eria",
|
||||
"7 Colored Fish",
|
||||
"Sea Serpent Warrior of Darkness",
|
||||
"Abyss Soldier"
|
||||
], player, 2) and state.has_any([
|
||||
"Giga Gagagigo",
|
||||
"Amphibian Beast",
|
||||
"Terrorking Salmon",
|
||||
"Mobius the Frost Monarch"
|
||||
], player) and state.has_from_list_exclusive([
|
||||
"Revival Jam",
|
||||
"Yomi Ship",
|
||||
"Treeborn Frog"
|
||||
], player, 2) and state.has("Mother Grizzly", player)
|
||||
|
||||
|
||||
def only_fire(state, player):
|
||||
return state.has_from_list_exclusive([
|
||||
"Blazing Inpachi",
|
||||
"Familiar-Possessed - Hiita",
|
||||
"Great Angus",
|
||||
"Fire Beaters"
|
||||
], player, 2) and state.has_any([
|
||||
"Thestalos the Firestorm Monarch",
|
||||
"Horus the Black Flame Dragon LV6"
|
||||
], player) and state.has_from_list_exclusive([
|
||||
"Solar Flare Dragon",
|
||||
"Tenkabito Shien",
|
||||
"Ultimate Baseball Kid"
|
||||
], player, 2) and state.has("UFO Turtle", player)
|
||||
|
||||
|
||||
def only_wind(state, player):
|
||||
return state.has_from_list_exclusive([
|
||||
"Luster Dragon",
|
||||
"Slate Warrior",
|
||||
"Spear Dragon",
|
||||
"Familiar-Possessed - Wynn",
|
||||
"Harpie's Brother",
|
||||
"Nin-Ken Dog",
|
||||
"Cyber Harpie Lady",
|
||||
"Oxygeddon"
|
||||
], player, 2) and state.has_any([
|
||||
"Cyber-Tech Alligator",
|
||||
"Luster Dragon #2",
|
||||
"Armed Dragon LV5",
|
||||
"Roc from the Valley of Haze"
|
||||
], player) and state.has_from_list_exclusive([
|
||||
"Armed Dragon LV3",
|
||||
"Twin-Headed Behemoth",
|
||||
"Harpie Lady 1"
|
||||
], player, 2) and state.has("Flying Kamakiri 1", player)
|
||||
|
||||
|
||||
def only_fairy(state, player):
|
||||
return state.has_any([
|
||||
"Dunames Dark Witch",
|
||||
"Hysteric Fairy"
|
||||
], player) and (state.count_from_list_exclusive([
|
||||
"Dunames Dark Witch",
|
||||
"Hysteric Fairy",
|
||||
"Dancing Fairy",
|
||||
"Zolga",
|
||||
"Shining Angel",
|
||||
"Kelbek",
|
||||
"Mudora",
|
||||
"Asura Priest",
|
||||
"Cestus of Dagla"
|
||||
], player) + (state.has_any([
|
||||
"The Agent of Judgment - Saturn",
|
||||
"Airknight Parshath"
|
||||
], player))) >= 7
|
||||
|
||||
|
||||
def only_warrior(state, player):
|
||||
return state.has_any([
|
||||
"Dark Blade",
|
||||
"Blindly Loyal Goblin",
|
||||
"D.D. Survivor",
|
||||
"Gearfried the Iron knight",
|
||||
"Ninja Grandmaster Sasuke",
|
||||
"Warrior Beaters"
|
||||
], player) and (state.count_from_list_exclusive([
|
||||
"Warrior Lady of the Wasteland",
|
||||
"Exiled Force",
|
||||
"Mystic Swordsman LV2",
|
||||
"Dimensional Warrior",
|
||||
"Dandylion",
|
||||
"D.D. Assailant",
|
||||
"Blade Knight",
|
||||
"D.D. Warrior Lady",
|
||||
"Marauding Captain",
|
||||
"Command Knight",
|
||||
"Reinforcement of the Army"
|
||||
], player) + (state.has_any([
|
||||
"Freed the Matchless General",
|
||||
"Holy Knight Ishzark",
|
||||
"Silent Swordsman Lv5"
|
||||
], player))) >= 7
|
||||
|
||||
|
||||
def only_zombie(state, player):
|
||||
return state.has("Pyramid Turtle", player) \
|
||||
and state.has_from_list_exclusive([
|
||||
"Regenerating Mummy",
|
||||
"Ryu Kokki",
|
||||
"Spirit Reaper",
|
||||
"Master Kyonshee",
|
||||
"Curse of Vampire",
|
||||
"Vampire Lord",
|
||||
"Goblin Zombie",
|
||||
"Curse of Vampire",
|
||||
"Vampire Lord",
|
||||
"Goblin Zombie",
|
||||
"Book of Life",
|
||||
"Call of the Mummy"
|
||||
], player, 6)
|
||||
|
||||
|
||||
def only_dragon(state, player):
|
||||
return state.has_any([
|
||||
"Luster Dragon",
|
||||
"Spear Dragon",
|
||||
"Cave Dragon"
|
||||
], player) and (state.count_from_list_exclusive([
|
||||
"Luster Dragon",
|
||||
"Spear Dragon",
|
||||
"Cave Dragon"
|
||||
"Armed Dragon LV3",
|
||||
"Masked Dragon",
|
||||
"Twin-Headed Behemoth",
|
||||
"Element Dragon",
|
||||
"Troop Dragon",
|
||||
"Horus the Black Flame Dragon LV4",
|
||||
"Stamping Destruction"
|
||||
], player) + (state.has_any([
|
||||
"Luster Dragon #2",
|
||||
"Armed Dragon LV5",
|
||||
"Kaiser Glider",
|
||||
"Horus the Black Flame Dragon LV6"
|
||||
], player))) >= 7
|
||||
|
||||
|
||||
def only_spellcaster(state, player):
|
||||
return state.has_any([
|
||||
"Dark Elf",
|
||||
"Gemini Elf",
|
||||
"Skilled Dark Magician",
|
||||
"Toon Gemini Elf",
|
||||
"Kycoo the Ghost Destroyer",
|
||||
"Familiar-Possessed - Aussa"
|
||||
], player) and (state.count_from_list_exclusive([
|
||||
"Dark Elf",
|
||||
"Gemini Elf",
|
||||
"Skilled Dark Magician",
|
||||
"Toon Gemini Elf",
|
||||
"Kycoo the Ghost Destroyer",
|
||||
"Familiar-Possessed - Aussa",
|
||||
"Breaker the magical Warrior",
|
||||
"The Tricky",
|
||||
"Injection Fairy Lily",
|
||||
"Magician of Faith",
|
||||
"Tsukuyomi",
|
||||
"Gravekeeper's Spy",
|
||||
"Gravekeeper's Guard",
|
||||
"Summon Priest",
|
||||
"Old Vindictive Magician",
|
||||
"Apprentice Magician",
|
||||
"Magical Dimension"
|
||||
], player) + (state.has_any([
|
||||
"Chaos Command Magician",
|
||||
"Cybernetic Magician"
|
||||
], player))) >= 7
|
||||
|
||||
|
||||
def equip_unions(state, player):
|
||||
return (state.has_all(["Burning Beast", "Freezing Beast",
|
||||
"Metallizing Parasite - Lunatite", "Mother Grizzly"], player) or
|
||||
state.has_all(["Dark Blade", "Pitch-Dark Dragon",
|
||||
"Giant Orc", "Second Goblin", "Mystic Tomato"], player) or
|
||||
state.has_all(["Decayed Commander", "Zombie Tiger",
|
||||
"Vampire Orchis", "Des Dendle", "Giant Rat"], player) or
|
||||
state.has_all(["Indomitable Fighter Lei Lei", "Protective Soul Ailin",
|
||||
"V-Tiger Jet", "W-Wing Catapult", "Shining Angel"], player) or
|
||||
state.has_all(["X-Head Cannon", "Y-Dragon Head", "Z-Metal Tank", "Shining Angel"], player)) and\
|
||||
state.has_any(["Frontline Base", "Formation Union", "Roll Out!"], player)
|
||||
|
||||
|
||||
def can_gain_lp_every_turn(state, player):
|
||||
return state.count_from_list_exclusive([
|
||||
"Solemn Wishes",
|
||||
"Cure Mermaid",
|
||||
"Dancing Fairy",
|
||||
"Princess Pikeru",
|
||||
"Kiseitai"], player) >= 3
|
||||
|
||||
|
||||
def only_normal(state, player):
|
||||
return (state.has_from_list_exclusive([
|
||||
"Archfiend Soldier",
|
||||
"Gemini Elf",
|
||||
"Insect Knight",
|
||||
"Luster Dragon",
|
||||
"Mad Dog of Darkness",
|
||||
"Vorse Raider",
|
||||
"Blazing Inpachi",
|
||||
"Gagagigo",
|
||||
"Mechanicalchaser",
|
||||
"7 Colored Fish",
|
||||
"Dark Blade",
|
||||
"Dunames Dark Witch",
|
||||
"Giant Red Snake",
|
||||
"Gil Garth",
|
||||
"Great Angus",
|
||||
"Harpie's Brother",
|
||||
"La Jinn the Mystical Genie of the Lamp",
|
||||
"Neo Bug",
|
||||
"Nin-Ken Dog",
|
||||
"Opticlops",
|
||||
"Sea Serpent Warrior of Darkness",
|
||||
"X-Head Cannon",
|
||||
"Zure, Knight of Dark World"], player, 6) and
|
||||
state.has_any([
|
||||
"Cyber-Tech Alligator",
|
||||
"Summoned Skull",
|
||||
"Giga Gagagigo",
|
||||
"Amphibian Beast",
|
||||
"Beast of Talwar",
|
||||
"Luster Dragon #2",
|
||||
"Terrorking Salmon"], player))
|
||||
|
||||
|
||||
def only_level(state, player):
|
||||
return (state.has("Level Up!", player) and
|
||||
(state.has_all(["Armed Dragon LV3", "Armed Dragon LV5"], player) +
|
||||
state.has_all(["Horus the Black Flame Dragon LV4", "Horus the Black Flame Dragon LV6"], player) +
|
||||
state.has_all(["Mystic Swordsman LV4", "Mystic Swordsman LV6"], player) +
|
||||
state.has_all(["Silent Swordsman Lv3", "Silent Swordsman Lv5"], player) +
|
||||
state.has_all(["Ultimate Insect Lv3", "Ultimate Insect Lv5"], player)) >= 3)
|
||||
|
||||
|
||||
def spell_counter(state, player):
|
||||
return (state.has("Pitch-Black Power Stone", player) and
|
||||
state.has_from_list_exclusive(["Blast Magician",
|
||||
"Magical Marionette",
|
||||
"Mythical Beast Cerberus",
|
||||
"Royal Magical Library",
|
||||
"Spell-Counter Cards"], player, 2))
|
||||
|
||||
|
||||
def take_control(state, player):
|
||||
return state.has_from_list_exclusive(["Aussa the Earth Charmer",
|
||||
"Jowls of Dark Demise",
|
||||
"Brain Control",
|
||||
"Creature Swap",
|
||||
"Enemy Controller",
|
||||
"Mind Control",
|
||||
"Magician of Faith"], player, 5)
|
||||
|
||||
|
||||
def only_toons(state, player):
|
||||
return state.has_all(["Toon Gemini Elf",
|
||||
"Toon Goblin Attack Force",
|
||||
"Toon Masked Sorcerer",
|
||||
"Toon Mermaid",
|
||||
"Toon Dark Magician Girl",
|
||||
"Toon World"], player)
|
||||
|
||||
|
||||
def only_spirit(state, player):
|
||||
return state.has_all(["Asura Priest",
|
||||
"Fushi No Tori",
|
||||
"Maharaghi",
|
||||
"Susa Soldier"], player)
|
||||
|
||||
|
||||
def pacman_deck(state, player):
|
||||
return state.has_from_list_exclusive(["Des Lacooda",
|
||||
"Swarm of Locusts",
|
||||
"Swarm of Scarabs",
|
||||
"Wandering Mummy",
|
||||
"Golem Sentry",
|
||||
"Great Spirit",
|
||||
"Royal Keeper",
|
||||
"Stealth Bird"], player, 4)
|
||||
|
||||
|
||||
def quick_plays(state, player):
|
||||
return state.has_from_list_exclusive(["Collapse",
|
||||
"Emergency Provisions",
|
||||
"Enemy Controller",
|
||||
"Graceful Dice",
|
||||
"Mystik Wok",
|
||||
"Offerings to the Doomed",
|
||||
"Poison of the Old Man",
|
||||
"Reload",
|
||||
"Rush Recklessly",
|
||||
"The Reliable Guardian"], player, 4)
|
||||
|
||||
|
||||
def counter_traps(state, player):
|
||||
return state.has_from_list_exclusive(["Cursed Seal of the Forbidden Spell",
|
||||
"Divine Wrath",
|
||||
"Horn of Heaven",
|
||||
"Magic Drain",
|
||||
"Magic Jammer",
|
||||
"Negate Attack",
|
||||
"Seven Tools of the Bandit",
|
||||
"Solemn Judgment",
|
||||
"Spell Shield Type-8"], player, 5)
|
||||
|
||||
|
||||
def back_row_removal(state, player):
|
||||
return state.has_from_list_exclusive(["Anteatereatingant",
|
||||
"B.E.S. Tetran",
|
||||
"Breaker the Magical Warrior",
|
||||
"Calamity of the Wicked",
|
||||
"Chiron the Mage",
|
||||
"Dust Tornado",
|
||||
"Heavy Storm",
|
||||
"Mystical Space Typhoon",
|
||||
"Mobius the Frost Monarch",
|
||||
"Raigeki Break",
|
||||
"Stamping Destruction",
|
||||
"Swarm of Locusts"], player, 2)
|
|
@ -0,0 +1,81 @@
|
|||
structure_contents: dict[str, set] = {
|
||||
"dragons_roar": {
|
||||
"Luster Dragon",
|
||||
"Armed Dragon LV3",
|
||||
"Armed Dragon LV5",
|
||||
"Masked Dragon",
|
||||
"Twin-Headed Behemoth",
|
||||
"Stamping Destruction",
|
||||
"Nobleman of Crossout",
|
||||
"Creature Swap",
|
||||
"Reload",
|
||||
"Stamping Destruction",
|
||||
"Heavy Storm",
|
||||
"Dust Tornado",
|
||||
"Mystical Space Typhoon",
|
||||
},
|
||||
"zombie_madness": {
|
||||
"Pyramid Turtle",
|
||||
"Regenerating Mummy",
|
||||
"Ryu Kokki",
|
||||
"Book of Life",
|
||||
"Call of the Mummy",
|
||||
"Creature Swap",
|
||||
"Reload",
|
||||
"Heavy Storm",
|
||||
"Dust Tornado",
|
||||
"Mystical Space Typhoon",
|
||||
},
|
||||
"blazing_destruction": {
|
||||
"Inferno",
|
||||
"Solar Flare Dragon",
|
||||
"UFO Turtle",
|
||||
"Ultimate Baseball Kid",
|
||||
"Fire Beaters",
|
||||
"Tribute to The Doomed",
|
||||
"Level Limit - Area B",
|
||||
"Heavy Storm",
|
||||
"Dust Tornado",
|
||||
"Mystical Space Typhoon",
|
||||
},
|
||||
"fury_from_the_deep": {
|
||||
"Mother Grizzly",
|
||||
"Water Beaters",
|
||||
"Gravity Bind",
|
||||
"Reload",
|
||||
"Mobius the Frost Monarch",
|
||||
"Heavy Storm",
|
||||
"Dust Tornado",
|
||||
"Mystical Space Typhoon",
|
||||
},
|
||||
"warriors_triumph": {
|
||||
"Gearfried the Iron Knight",
|
||||
"D.D. Warrior Lady",
|
||||
"Marauding Captain",
|
||||
"Exiled Force",
|
||||
"Reinforcement of the Army",
|
||||
"Warrior Beaters",
|
||||
"Reload",
|
||||
"Heavy Storm",
|
||||
"Dust Tornado",
|
||||
"Mystical Space Typhoon",
|
||||
},
|
||||
"spellcasters_judgement": {
|
||||
"Dark Magician",
|
||||
"Apprentice Magician",
|
||||
"Breaker the Magical Warrior",
|
||||
"Magician of Faith",
|
||||
"Skilled Dark Magician",
|
||||
"Tsukuyomi",
|
||||
"Magical Dimension",
|
||||
"Mage PowerSpell-Counter Cards",
|
||||
"Heavy Storm",
|
||||
"Dust Tornado",
|
||||
"Mystical Space Typhoon",
|
||||
},
|
||||
"none": {},
|
||||
}
|
||||
|
||||
|
||||
def get_deck_content_locations(deck: str) -> dict[str, str]:
|
||||
return {f"{deck} {i}": content for i, content in enumerate(structure_contents[deck])}
|
Loading…
Reference in New Issue