Skip to content

Add 'Oops All <Boss> Mode#142

Open
wrjones104 wants to merge 4 commits into
ff6wc:devfrom
wrjones104:oops-all-boss
Open

Add 'Oops All <Boss> Mode#142
wrjones104 wants to merge 4 commits into
ff6wc:devfrom
wrjones104:oops-all-boss

Conversation

@wrjones104

Copy link
Copy Markdown
Collaborator

Feature: "Oops, All X!" Randomizer Flag (-oops <id/name>)

Adds the -oops flag, which replaces all boss, dragon, and statue encounters with a single chosen boss.

Implementation Details

Input Handling:

  • Accepts integer IDs (0–383) or case-insensitive, normalized string names (e.g., "MagiMaster" or "magi master").
  • If the ID/name is invalid, it throws a ValueError pointing to data/bosses.py.
  • Strings are resolved to integer IDs in process(args) to keep downstream logic consistent.

Progression & Objectives:

  • Maintains original formation IDs for all encounters. This ensures that post-battle bitmasks, defeat counts, and progression triggers (like unlocking Kefka's Tower) function normally.

Graphics & VRAM:

  • To prevent VRAM/sprite overlap issues in multi-boss battles, enemy_slots is forced to 1.
  • The chosen boss is centered on screen (y=5, x=6).
  • Uses the boss's native formation mold to ensure correct sprite rendering and VRAM allocation.

Notes:

  • For the Final Battle, only Final Kefka is affected by this flag

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the "Oops, all !" feature, which allows users to replace all bosses in the game with a single specified boss via a new -oops command-line argument. The changes include argument parsing and validation in args/bosses.py and the implementation of the replacement logic in data/enemy_formations.py, which also handles boss positioning and VRAM mold application. Reviewers suggested several improvements to simplify the code, such as using aggregated dictionaries for boss lookups, utilizing set operations for ID filtering, and employing the any() function for more idiomatic formation checks.

Comment thread args/bosses.py
Comment thread data/enemy_formations.py
Comment thread data/enemy_formations.py Outdated
Comment thread data/enemy_formations.py
Comment thread args/graphics.py Outdated
@BriGuy7727

Copy link
Copy Markdown
Collaborator

How does this mode work with the Bosses number objective condition? Previously, it was a unique boss counter to satisfy that objective condition...if let's say someone makes Unlock Kefka Bosses = 3, then do they softlock themselves into never beating the seed?

@wrjones104

Copy link
Copy Markdown
Collaborator Author

How does this mode work with the Bosses number objective condition? Previously, it was a unique boss counter to satisfy that objective condition...if let's say someone makes Unlock Kefka Bosses = 3, then do they softlock themselves into never beating the seed?

This basically retains the original formation, just swapping in the actual "oops" boss into it. The number of bosses is counted up by the formation ID, so even though every single boss might be "Leader", the formations will be "Magi Master" or "Cranes", and would trigger any boss checks or requirements like that. So even if you have an objective to "Defeat Stooges", and your "Oops" boss is "Ultros 1", one of those "Ultros 1" bosses will be in the "Stooges" formation.

- Improved validation of boss IDs to ensure only valid IDs are accepted.
- Simplified the process of finding a boss's native mold by directly checking formations.
- Added more descriptive error messages for invalid boss IDs.
@wrjones104

Copy link
Copy Markdown
Collaborator Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an "Oops, all !" feature, allowing players to replace all bosses with a specific boss enemy ID, name, or a random boss. This includes adding a new -oops command-line argument, parsing and validating the input, and modifying enemy formations to replace existing bosses with the target boss while adjusting positioning and applying the native mold. The review feedback suggests two main improvements: simplifying the argument parsing logic in args/bosses.py by using str.isdigit() instead of a try-except block for control flow, and refactoring the nested loop in data/enemy_formations.py to use Python's built-in any() function along with the formation.enemies() helper for cleaner and more Pythonic code.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread args/bosses.py
Comment on lines +63 to +92
try:
# Try to parse as integer ID first
oops_id = int(args.oops)
if oops_id not in valid_boss_ids:
raise ValueError(f"Invalid boss ID: {oops_id}. Must be a valid boss enemy ID.")
args.oops = oops_id
except ValueError as e:
if "Invalid boss ID" in str(e):
raise e

# If not a valid integer ID, try to parse as normalized name
def normalize(name):
return "".join(c.lower() for c in name if c.isalnum())

name_to_id = {}
for enemy_dict in [bosses.normal_enemy_name, bosses.dragon_enemy_name, bosses.statue_enemy_name, bosses.final_battle_enemy_name]:
for eid, name in enemy_dict.items():
if eid not in excluded_final_battle_ids:
name_to_id[normalize(name)] = eid

normalized_input = normalize(args.oops)
if normalized_input in name_to_id:
args.oops = name_to_id[normalized_input]
elif normalized_input == "random":
args.oops = "random"
else:
raise ValueError(
f"Invalid boss ID or name: '{args.oops}'. "
f"Please check the enemy maps in data/bosses.py for correct names and IDs."
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of using a try-except block to handle control flow and checking the exception string to decide whether to re-raise, you can check if the input is numeric using str.isdigit(). This makes the logic cleaner, more readable, and avoids relying on exception message parsing.

        if args.oops.isdigit():
            oops_id = int(args.oops)
            if oops_id not in valid_boss_ids:
                raise ValueError(f"Invalid boss ID: {oops_id}. Must be a valid boss enemy ID.")
            args.oops = oops_id
        else:
            def normalize(name):
                return "".join(c.lower() for c in name if c.isalnum())

            name_to_id = {}
            for enemy_dict in [bosses.normal_enemy_name, bosses.dragon_enemy_name, bosses.statue_enemy_name, bosses.final_battle_enemy_name]:
                for eid, name in enemy_dict.items():
                    if eid not in excluded_final_battle_ids:
                        name_to_id[normalize(name)] = eid

            normalized_input = normalize(args.oops)
            if normalized_input in name_to_id:
                args.oops = name_to_id[normalized_input]
            elif normalized_input == "random":
                args.oops = "random"
            else:
                raise ValueError(
                    f"Invalid boss ID or name: '{args.oops}'. "
                    f"Please check the enemy maps in data/bosses.py for correct names and IDs."
                )

Comment thread data/enemy_formations.py
Comment on lines +218 to +225
has_boss = False
for enemy_index in range(formation.ENEMY_CAPACITY):
if formation.enemy_slots & (1 << enemy_index):
if formation.enemy_ids[enemy_index] in boss_enemy_ids:
has_boss = True
break

if has_boss:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This nested loop can be simplified and made more Pythonic by using the built-in any() function along with the existing formation.enemies() helper method, which already filters and returns the active enemy IDs for the formation.

Suggested change
has_boss = False
for enemy_index in range(formation.ENEMY_CAPACITY):
if formation.enemy_slots & (1 << enemy_index):
if formation.enemy_ids[enemy_index] in boss_enemy_ids:
has_boss = True
break
if has_boss:
if any(enemy_id in boss_enemy_ids for enemy_id in formation.enemies()):

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants