Skip to content

Adding a Forfeit Option in the duels

Sha0den edited this page Jan 21, 2025 · 2 revisions

Hello! In this tutorial, we are going to add a way for the player to forfeit a duel. If given the option, some players might prefer to give up rather than continue to spend their time participating in a duel that isn't possible to win. Ideally, this option would appear directly in one of the menus, but since menu space is already a little tight, this tutorial will show you how to set up another duel shortcut.


We'll begin by opening src/engine/duel/core.asm, which contains most of the code relating to the duel engine. Scroll down to the PrintDuelMenuAndHandleInput function, and add another conditional jump for the SELECT button at the end of the .handle_input subroutine (line 329 in the base disassembly.) Since nearly all of the button combinations involving the B button are currently assigned to other shortcuts, we're forced to use B + SELECT for our concede option.

 	...
 	bit D_RIGHT_F, a
 	jr nz, DuelMenuShortcut_OpponentDiscardPile
 	bit START_F, a
 	jp nz, DuelMenuShortcut_OpponentActivePokemon
+	bit SELECT_F, a
+	jp nz, DuelMenuShortcut_ConcedeDuel

 .b_not_held
 	ldh a, [hKeysPressed]
 	and START
 	...

Now, we'll need to define the DuelMenuShortcut_ConcedeDuel function somewhere in src/engine/duel/core.asm. For this tutorial, we'll place the new function after DuelMenuShortcut_PlayerDiscardPile. This new code will be accessed whenever the Player holds down the B button and then presses the SELECT button. It will then ask the player whether they want to concede. If "No" is selected, then the main duel menu (Hand, Check, Retreat, etc.) will return and the duel will continue, but if "Yes" is selected, then the TURN_PLAYER_LOST constant will be loaded into wDuelFinished, a wram address that's used to assess the outcome of the duel during MainDuelLoop. This will cause the duel to end with the opponent declared the winner.

 DuelMenuShortcut_PlayerDiscardPile:
 	call OpenTurnHolderDiscardPileScreen
 	jp c, PrintDuelMenuAndHandleInput
 	jp DuelMainInterface
+
+; triggered by pressing B + SELECT in the duel menu
+DuelMenuShortcut_ConcedeDuel:
+	ldtx hl, WouldYouLikeToConcedeText
+	call YesOrNoMenuWithText
+	jp c, PrintDuelMenuAndHandleInput ; return to main duel menu if "No" was selected
+	; Player chose to concede
+	ld a, TURN_PLAYER_LOST
+	ld [wDuelFinished], a
+	ret

; draw the non-turn holder's play area screen
OpenNonTurnHolderPlayAreaScreen:
	call SwapTurn
	call OpenTurnHolderPlayAreaScreen

We're not quite done. We referenced a text that doesn't yet exist. All of the game's text data is located in src/text. You can either replace an unused text or add the following text to any of the text files that isn't full. You may want to review the Add new text tutorial if you're still unfamiliar with the process.

WouldYouLikeToConcedeText:
	text "     Would you like to concede?"
	done

Congratulations! You've successfully added a concede option to your game. If you're curious what it will look like, here are a couple of screenshots. Technically, this shortcut will be available during any duel. If you intend to retain the Practice Duel with Sam, then you may want to consider disabling the shortcut during that by checking the value stored in wIsPracticeDuel before jumping to DuelMenuShortcut_ConcedeDuel, but that's entirely up to you.