Skip to content

Don't allow first turn attacks

ElectroDeoxys edited this page Jun 22, 2024 · 3 revisions

In modern TCG rules, the player that plays first is not allowed to perform their attack. This is an easy modification to the duel engine since there's already a WRAM variable that keeps track of the number of turns that have elapsed in a duel, wDuelTurns.

Contents

  1. Disallow player attack on first turn
  2. Disallow opponent attack on first turn

1. Disallow player attack on first turn

We shall stop player access to the attack menu during the first turn. Edit src/engine/duel/core.asm:

 ; triggered by selecting the "Attack" item in the duel menu
 DuelMenu_Attack:
+       ; can't attack on first turn
+       ld a, [wDuelTurns]
+       or a
+       ldtx hl, YouCannotAttackOnFirstTurnText
+       jr z, .alert_cant_attack_and_cancel_menu
+
        call HandleCantAttackSubstatus
        jr c, .alert_cant_attack_and_cancel_menu
        call CheckIfActiveCardParalyzedOrAsleep

Here the logic is simple, if wDuelTurns is 0 (first turn), then print a message and close the menu. We will add this new text ID to the text offsets by overwriting an unused entry. Edit src/text/text_offsets.asm:

 TextOffsets::
        ...
        textpointer TheEnergyCardFromPlayAreaWasMovedText              ; 0x014c
        textpointer DrewFireEnergyFromTheHandText                      ; 0x014d
        textpointer ThePkmnCardsInHandAndDeckWereShuffledText          ; 0x014e
-       textpointer UnusedText014f                                     ; 0x014f
+       textpointer YouCannotAttackOnFirstTurnText                     ; 0x014f
        textpointer ChoosePokemonToRemoveDamageCounterFromText         ; 0x0150
        textpointer ChooseCardToDiscardFromHandText                    ; 0x0151
        textpointer ChoosePokemonToRemoveEnergyFromText                ; 0x0152

Then overwrite the corresponding text in src/text/text2.asm:

 ThePkmnCardsInHandAndDeckWereShuffledText:
        line "Hand and Deck were shuffled"
        done

-UnusedText014f: ; Unused
-       text "Remove Damage counter each time the"
-       line "A Button is pressed. B Button quits."
+YouCannotAttackOnFirstTurnText:
+       text "You cannot attack on"
+       line "your first turn."
        done

2. Disallow opponent attack on first turn

Next we have to make it so that the AI follows this rule as well. After some inspection, we can see that AIProcessAttacks is called everytime the AI tries to attack. This seems like a logical point to place the condition. Edit src/engine/duel/ai/attacks.asm:

 AIProcessAttacks:
+       ; can't attack on first turn
+       ld a, [wDuelTurns]
+       or a
+       ret z
+
 ; if AI used Pluspower, load its attack index
        ld a, [wPreviousAIFlags]
        and AI_FLAG_USED_PLUSPOWER

Similar to the code we have added for the player, except we just return if wDuelTurns is equal to 0. The important aspect here is that this returns without carry set, which means the caller of the AIProcessAttacks routine will know that no attack was performed and will end the turn accordingly.

A common bug that might occur when relying on a counter is that at some point it might overflow and wrap back down to 0. In this case, wDuelTurns is an 8-bit variable keeping track of the duel turn, so it will overflow when it reaches 256. Given that each player has 60 card decks (but effectively start with a deck of 47-52 cards, depending on number of prize cards) reaching turn 120 is virtually guaranteed to deck out one or both of them. In light of this, an overflow is not likely to happen and so is not a concern.