• ¯\_(ツ)_/¯

Marrec immadur de 25 anys. M'agrada parlar català, but I can also write stuff in English. A veces, español. Programo, faig de TO pel Rivals of Aether i soc organitzador de la site de Barcelona de la Global Game Jam.


I said a few days ago that I was tinkering with the disassembly project for gen 1, and from time to time I come across beautiful stuff I previously had never read about.

The finding of the day is the bit of code that checks if a move is super effective and if the move has STAB,Same Type Attack Bonus to be more specific, the beginning of the routine, which looks like this1:


; function to adjust the base damage of an attack to account for type effectiveness
AdjustDamageForMoveType:
; values for player turn
	ld hl, wBattleMonType
	ld a, [hli]
	ld b, a    ; b = type 1 of attacker
	ld c, [hl] ; c = type 2 of attacker
	ld hl, wEnemyMonType
	ld a, [hli]
	ld d, a    ; d = type 1 of defender
	ld e, [hl] ; e = type 2 of defender
	ld a, [wPlayerMoveType]
	ld [wMoveType], a
	ldh a, [hWhoseTurn]
	and a
	jr z, .next
; values for enemy turn
	ld hl, wEnemyMonType
	ld a, [hli]
	ld b, a    ; b = type 1 of attacker
	ld c, [hl] ; c = type 2 of attacker
	ld hl, wBattleMonType
	ld a, [hli]
	ld d, a    ; d = type 1 of defender
	ld e, [hl] ; e = type 2 of defender
	ld a, [wEnemyMoveType]
	ld [wMoveType], a
.next
	; [...]

If you're not familiar with assembly code for the GameBoy, here's a rough pseudocode translation:

AdjustDamageForMoveType(){
	var attackerType1 = player'sMonType1
	var attackerType2 = player'sMonType2
	var defenderType1 = enemy'sMonType1
	var defenderType2 = enemy'sMonType2
	var attackType = player'sAttackType
	if (currentTurn == enemy'sTurn){
		attackerType1 = enemy'sMonType1
		attackerType2 = enemy'sMonType2
		defenderType1 = player'sMonType1
		defenderType2 = player'sMonType2
		attackType = enemy'sAttackType
	}
// [...]
}

Yes. The game is loading into the 5 different registers your types, the enemy's and your move's; and then it checks for whether it is even your turn to begin with. And if it is not, it loads them again in the correct order (alongside the correct type for the move). From memory. Instead of, you know, checking whose turn it is before doing anything so that the game doesn't waste 20 CPU cycles2 half of the times it checks for the damage calculation.

I know this is extremely far from this game's biggest coding sin, I just happened to come across the function while trying to implement a half-assed Tera Blast (where the move's type becomes your primary type), and found it hilarious.


  1. https://github.com/pret/pokered/blob/master/engine/battle/core.asm#L5200

  2. 0.00476 milliseconds


You must log in to comment.