Skip to content

Commit

Permalink
YGO06: added opponent shuffle
Browse files Browse the repository at this point in the history
  • Loading branch information
Rensen3 committed Jan 19, 2024
1 parent 739f1e3 commit 1084158
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 53 deletions.
94 changes: 58 additions & 36 deletions worlds/yugioh06/Opponents.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ class OpponentData(NamedTuple):
deck_file: str = ''
rule: Callable[[CollectionState], bool] = lambda state: True

opponets = [
def tier(self, tier):
self.tier = tier

def column(self, column):
self.column = column


challenge_opponents = [
OpponentData(27, "Exarion Universe", [], 1, 1, 5452, 13001, "deck/theme_001.ydc\x00\x00\x00\x00"),
OpponentData(28, "Stone Statue of the Aztecs", [], 1, 1, 4754, 13002, "deck/theme_002.ydc\x00\x00\x00\x00"),
OpponentData(29, "Raging Flame Sprite", [], 1, 1, 6189, 13003, "deck/theme_003.ydc\x00\x00\x00\x00"),
Expand Down Expand Up @@ -97,9 +104,37 @@ class OpponentData(NamedTuple):
OpponentData(101, "Alkana Knight Joker", [], 1, 1, 6454, 23023, "deck/limit_023.ydc\x00\x00\x00\x00"),
OpponentData(102, "Sorcerer of Dark Magic", [], 1, 1, 6086, 23024, "deck/limit_024.ydc\x00\x00\x00\x00"),
OpponentData(103, "Shinato, King of a Higher Plane", [], 1, 1, 5697, 23025, "deck/limit_025.ydc\x00\x00\x00\x00"),
OpponentData(104, "Ryu Kokki", [], 1, 1, 5902, 23026, "deck/limit_027.ydc\x00\x00\x00\x00"),
OpponentData(105, "Cyber Dragon", [], 1, 1, 6390, 23027, "deck/limit_028.ydc\x00\x00\x00\x00"),
OpponentData(106, "Ryu Kokki", [], 1, 1, 6405, 23028, "deck/limit_029.ydc\x00\x00\x00\x00"),
OpponentData(107, "Dark Dreadroute", [], 1, 1, 6319, 23029, "deck/limit_030.ydc\x00\x00\x00\x00"),
OpponentData(108, "Thestalos the Firestorm Monarch", [], 1, 1, 6190, 23030, "deck/limit_031.ydc\x00\x00\x00\x00"),
OpponentData(109, "Master of Oz", [], 1, 1, 6127, 23031, "deck/limit_032.ydc\x00\x00\x00\x00"),
OpponentData(110, "Orca Mega-Fortress of Darkness", [], 1, 1, 5896, 23032, "deck/limit_033.ydc\x00\x00\x00\x00"),
OpponentData(111, "Airknight Parshath", [], 1, 1, 5023, 23033, "deck/limit_034.ydc\x00\x00\x00\x00"),
OpponentData(112, "Dark Scorpion Burglars", [], 1, 1, 5425, 23034, "deck/limit_035.ydc\x00\x00\x00\x00"),
OpponentData(113, "Gilford the Lightning", [], 1, 1, 5451, 23035, "deck/limit_036.ydc\x00\x00\x00\x00"),
OpponentData(114, "Embodiment of Apophis", [], 1, 1, 5234, 23036, "deck/limit_037.ydc\x00\x00\x00\x00"),
OpponentData(115, "Great Maju Garzett", [], 1, 1, 5768, 23037, "deck/limit_038.ydc\x00\x00\x00\x00"),
OpponentData(116, "Black Luster Soldier - Envoy of the Beginning", [], 1, 1, 5835, 23038,
"deck/limit_039.ydc\x00\x00\x00\x00"),
OpponentData(117, "Red-Eyes B. Dragon", [], 1, 1, 4088, 23039, "deck/limit_040.ydc\x00\x00\x00\x00"),
OpponentData(118, "Blue-Eyes White Dragon", [], 1, 1, 4007, 23040, "deck/limit_041.ydc\x00\x00\x00\x00"),
OpponentData(119, "Dark Magician", [], 1, 1, 4041, 23041, "deck/limit_042.ydc\x00\x00\x00\x00"),
OpponentData(0, "Kuriboh SD", [], 1, 1, 4064, 1510, "deck/SD0_STARTER.ydc\x00\x00"),
OpponentData(10, "Red-Eyes Darkness Dragon SD", [], 1, 1, 6292, 1511, "deck/SD1_DRAGON.ydc\x00\x00\x00"),
OpponentData(11, "Vampire Genesis SD", [], 1, 1, 6293, 1512, "deck/SD2_UNDEAD.ydc\x00\x00\x00"),
OpponentData(12, "Infernal Flame Emperor SD", [], 1, 1, 6294, 1513, "deck/SD3_FIRE.ydc\x00\x00\x00\x00\x00"),
OpponentData(13, "Ocean Dragon Lord - Neo-Daedalus", [], 1, 1, 6295, 1514,
"deck/SD4_UMI.ydc\x00\x00\x00\x00\x00\x00"),
OpponentData(15, "Gilford the Legend", [], 1, 1, 6456, 1515, "deck/SD5_SOLDIER.ydc\x00\x00"),
OpponentData(16, "Dark Eradicator Warlock", [], 1, 1, 6530, 1516, "deck/SD6_MAGICIAN.ydc\x00"),
OpponentData(17, "Guardian Exode", [], 1, 1, 6640, 1517, "deck/SD7_GANSEKI.ydc\x00\x00"),
OpponentData(7, "Goblin King 2", ["Quick-Finish"], 2, 3, 5973, 8007, "deck/LV2_kingG2.ydc\x00\x00\x00"),
]

def get_opponents(multiworld: Optional[MultiWorld], player: Optional[int]) -> Tuple[OpponentData, ...]:

def get_opponents(multiworld: Optional[MultiWorld], player: Optional[int], randomize: bool = False) -> Tuple[OpponentData, ...]:
opponents_table: List[OpponentData] = [
# Tier 1
OpponentData(0, "Kuriboh", [], 1, 1, 4064, 8000, "deck/LV1_kuriboh.ydc\x00\x00"),
Expand Down Expand Up @@ -138,7 +173,8 @@ def get_opponents(multiworld: Optional[MultiWorld], player: Optional[int]) -> Tu
lambda state: state.yugioh06_difficulty(player, 3)),
OpponentData(18, "Goldd, Wu-Lord of Dark World", ["Quick-Finish"], 4, 4, 6505, 8018, "deck/LV4_ankokukai.ydc",
lambda state: state.yugioh06_difficulty(player, 3)),
OpponentData(19, "Elemental Hero Erikshieler", ["Quick-Finish"], 4, 5, 6639, 8019, "deck/LV4_Ehero.ydc\x00\x00\x00\x00",
OpponentData(19, "Elemental Hero Erikshieler", ["Quick-Finish"], 4, 5, 6639, 8019,
"deck/LV4_Ehero.ydc\x00\x00\x00\x00",
lambda state: state.yugioh06_difficulty(player, 3)),
# Tier 5
OpponentData(20, "Raviel, Lord of Phantasms", [], 5, 1, 6565, 8020, "deck/LV5_ravieru.ydc\x00\x00",
Expand All @@ -152,40 +188,26 @@ def get_opponents(multiworld: Optional[MultiWorld], player: Optional[int]) -> Tu
OpponentData(24, "Cyber End Dragon", ["Goal"], 5, 5, 6397, 8024, "deck/LV5_cyber.ydc\x00\x00\x00\x00",
lambda state: state.yugioh06_difficulty(player, 7)),
]
return tuple(opponents_table)

if not randomize:
return tuple(opponents_table)
opponents = opponents_table + challenge_opponents
goal = multiworld.random.choice([o for o in opponents if "Goal" in o.campaignInfo])
opponents.remove(goal)
multiworld.random.shuffle(opponents)
chosen_ones = opponents[:24]
chosen_ones.append(goal)
tier = 1
column = 1
recreation = []
for opp in chosen_ones:
recreation.append(OpponentData(opp.id, opp.name, opp.campaignInfo, tier, column, opp.card_id,
opp.deck_name_id, opp.deck_file, opp.rule))
column = column + 1
if column > 5:
column = 1
tier = tier + 1

def get_other_opponents(multiworld: Optional[MultiWorld], player: Optional[int]) -> Tuple[OpponentData, ...]:
opponents_table: List[OpponentData] = [
OpponentData(104, "Ryu Kokki", [], 1, 1, 5902, 23026, "deck/limit_027.ydc\x00\x00\x00\x00"),
OpponentData(105, "Cyber Dragon", [], 1, 1, 6390, 23027, "deck/limit_028.ydc\x00\x00\x00\x00"),
OpponentData(106, "Ryu Kokki", [], 1, 1, 6405, 23028, "deck/limit_029.ydc\x00\x00\x00\x00"),
OpponentData(107, "Dark Dreadroute", [], 1, 1, 6319, 23029, "deck/limit_030.ydc\x00\x00\x00\x00"),
OpponentData(108, "Thestalos the Firestorm Monarch", [], 1, 1, 6190, 23030, "deck/limit_031.ydc\x00\x00\x00\x00"),
OpponentData(109, "Master of Oz", [], 1, 1, 6127, 23031, "deck/limit_032.ydc\x00\x00\x00\x00"),
OpponentData(110, "Orca Mega-Fortress of Darkness", [], 1, 1, 5896, 23032, "deck/limit_033.ydc\x00\x00\x00\x00"),
OpponentData(111, "Airknight Parshath", [], 1, 1, 5023, 23033, "deck/limit_034.ydc\x00\x00\x00\x00"),
OpponentData(112, "Dark Scorpion Burglars", [], 1, 1, 5425, 23034, "deck/limit_035.ydc\x00\x00\x00\x00"),
OpponentData(113, "Gilford the Lightning", [], 1, 1, 5451, 23035, "deck/limit_036.ydc\x00\x00\x00\x00"),
OpponentData(114, "Embodiment of Apophis", [], 1, 1, 5234, 23036, "deck/limit_037.ydc\x00\x00\x00\x00"),
OpponentData(115, "Great Maju Garzett", [], 1, 1, 5768, 23037, "deck/limit_038.ydc\x00\x00\x00\x00"),
OpponentData(116, "Black Luster Soldier - Envoy of the Beginning", [], 1, 1, 5835, 23038, "deck/limit_039.ydc\x00\x00\x00\x00"),
OpponentData(117, "Red-Eyes B. Dragon", [], 1, 1, 4088, 23039, "deck/limit_040.ydc\x00\x00\x00\x00"),
OpponentData(118, "Blue-Eyes White Dragon", [], 1, 1, 4007, 23040, "deck/limit_041.ydc\x00\x00\x00\x00"),
OpponentData(119, "Dark Magician", [], 1, 1, 4041, 23041, "deck/limit_042.ydc\x00\x00\x00\x00"),
OpponentData(0, "Kuriboh SD", [], 1, 1, 4064, 1510, "deck/SD0_STARTER.ydc\x00\x00"),
OpponentData(10, "Red-Eyes Darkness Dragon SD", [], 1, 1, 6292, 1511, "deck/SD1_DRAGON.ydc\x00\x00\x00"),
OpponentData(11, "Vampire Genesis SD", [], 1, 1, 6293, 1512, "deck/SD2_UNDEAD.ydc\x00\x00\x00"),
OpponentData(12, "Infernal Flame Emperor SD", [], 1, 1, 6294, 1513, "deck/SD3_FIRE.ydc\x00\x00\x00\x00\x00"),
OpponentData(13, "Ocean Dragon Lord - Neo-Daedalus", [], 1, 1, 6295, 1514, "deck/SD4_UMI.ydc\x00\x00\x00\x00\x00\x00"),
OpponentData(15, "Gilford the Legend", [], 1, 1, 6456, 1515, "deck/SD5_SOLDIER.ydc\x00\x00"),
OpponentData(16, "Dark Eradicator Warlock", [], 1, 1, 6530, 1516, "deck/SD6_MAGICIAN.ydc\x00"),
OpponentData(17, "Guardian Exode", [], 1, 1, 6640, 1517, "deck/SD7_GANSEKI.ydc\x00\x00"),
OpponentData(7, "Goblin King 2", ["Quick-Finish"], 2, 3, 5973, 8007, "deck/LV2_kingG2.ydc\x00\x00\x00",
lambda state: state.yugioh06_difficulty(player, 1)),

]
return tuple(opponents_table)
return tuple(recreation)


def get_opponent_locations(opponent: OpponentData) -> dict[str, str]:
Expand Down
7 changes: 7 additions & 0 deletions worlds/yugioh06/Options.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class MoneyRewardMultiplier(Range):
class NormalizeBoostersPacks(Toggle):
"""If enabled every booster pack costs the same otherwise vanilla cost is used"""
display_name = "Normalize Booster Packs"
default = True


class BoosterPackPrices(Range):
Expand All @@ -142,6 +143,11 @@ class AddEmptyBanList(Toggle):
display_name = "Add Empty Ban List"


class CampaignOpponentsShuffle(Toggle):
"""Replaces the campaign with random opponents from the entire game"""
display_name = "Campaign Opponents Shuffle"
default = False

@dataclass
class Yugioh06Options(PerGameCommonOptions):
structure_deck: StructureDeck
Expand All @@ -161,3 +167,4 @@ class Yugioh06Options(PerGameCommonOptions):
normalize_boosters_packs: NormalizeBoostersPacks
booster_pack_prices: BoosterPackPrices
add_empty_banList: AddEmptyBanList
campaign_opponents_shuffle: CampaignOpponentsShuffle
2 changes: 1 addition & 1 deletion worlds/yugioh06/Rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def set_rules(world):
lambda state: state.has_any(["Reasoning", "Monster Gate", "Magical Merchant"], player) and
state.yugioh06_difficulty(player, 2),
"Exactly 0 LP Bonus": lambda state: state.yugioh06_difficulty(player, 2),
"Quick Finish Bonus": lambda state: state.has("Quick-Finish", player),
"Quick Finish Bonus": lambda state: state.has("Quick-Finish", player) or state.yugioh06_difficulty(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),
Expand Down
31 changes: 15 additions & 16 deletions worlds/yugioh06/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
challenges, useful
from .Locations import Bonuses, Limited_Duels, Theme_Duels, Campaign_Opponents, Required_Cards, \
get_beat_challenge_events, special, collection_events
from .Opponents import get_opponents, get_opponent_locations, get_other_opponents
from .Opponents import get_opponents, get_opponent_locations
from .Options import Yugioh06Options
from .Rom import YGO06DeltaPatch, get_base_rom_path, MD5Europe, MD5America
from .Rules import set_rules
Expand Down Expand Up @@ -113,6 +113,7 @@ def __init__(self, world: MultiWorld, player: int):
self.removed_challenges = None
self.starting_booster = None
self.starting_opponent = None
self.campaign_opponents = None

def create_item(self, name: str) -> Item:
return Item(name, ItemClassification.progression, self.item_name_to_id[name], self.player)
Expand Down Expand Up @@ -158,7 +159,7 @@ def create_items(self):
location.place_locked_item(item)
location.event = True

for opponent in get_opponents(self.multiworld, self.player):
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(
Expand Down Expand Up @@ -226,7 +227,7 @@ def create_regions(self):

campaign = self.multiworld.get_region('Campaign', self.player)
# Campaign Opponents
for opponent in get_opponents(self.multiworld, self.player):
for opponent in self.campaign_opponents:
unlock_item = "Campaign Tier " + str(opponent.tier) + " Column " + str(opponent.column)
region = create_region(self,
opponent.name, get_opponent_locations(opponent))
Expand Down Expand Up @@ -322,6 +323,8 @@ def generate_early(self):
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 apply_base_path(self, rom):
base_patch_location = "/".join((os.path.dirname(self.__file__), "patch.bsdiff4"))
Expand Down Expand Up @@ -442,19 +445,15 @@ def apply_randomizer(self):
rom_data[0x1e5e2e8 + space] = booster_pack_price[0]
rom_data[0x1e5e2e9 + space] = booster_pack_price[1]
rom_data[0x1e5e2ea + space] = 5
for i in range(0, 121):
space = i * 32
print(str(i) + ": " + str(int.from_bytes(rom_data[0x1e58d0e + space:0x1e58d10 + space], 'little')) + ', ' +
str(int.from_bytes(rom_data[0x1e58d10 + space:0x1e58d12 + space], 'little')) + ', "' +
rom_data[0x1e58d12 + space:0x1e58d28 + space].decode('ascii').replace("\x00", "\\x00") + '",')
i = 0
for opp in get_other_opponents(self.multiworld, self.player):
space = i * 32
rom_data[0x000f3ba + i] = opp.id
rom_data[0x1e58d0e + space:0x1e58d10 + space] = opp.card_id.to_bytes(2, 'little')
rom_data[0x1e58d10 + space:0x1e58d12 + space] = opp.deck_name_id.to_bytes(2, 'little')
rom_data[0x1e58d12 + space:0x1e58d28 + space] = opp.deck_file.encode('ascii')
i = i+1
if self.options.campaign_opponents_shuffle.value:
i = 0
for opp in self.campaign_opponents:
space = i * 32
rom_data[0x000f3ba + i] = opp.id
rom_data[0x1e58d0e + space:0x1e58d10 + space] = opp.card_id.to_bytes(2, 'little')
rom_data[0x1e58d10 + space:0x1e58d12 + space] = opp.deck_name_id.to_bytes(2, 'little')
rom_data[0x1e58d12 + space:0x1e58d28 + space] = opp.deck_file.encode('ascii')
i = i+1
return rom_data

def generate_output(self, output_directory: str):
Expand Down

0 comments on commit 1084158

Please sign in to comment.