mvbg

VM_RPN

VM_RPN is a GBVM instruction that initiates a Reverse Polish Notation (RPN) calculation block. It allows you to perform complex arithmetic and logical operations using a stack-based approach.

Purpose: RPN is a mathematical notation where every operator follows all of its operands. For example, to express 3 + 4, you would write 3 4 +. This notation is particularly well-suited for stack-based virtual machines like the GBVM because it eliminates the need for parentheses and simplifies parsing. VM_RPN is essential for:

When VM_RPN is executed, the GBVM enters a special RPN evaluation mode. Subsequent instructions within this block (like .R_INT8, .R_REF_IND, .R_OPERATOR, .R_REF_MEM_SET) manipulate values on the RPN stack. The final result of the RPN expression is typically left on the VM’s main stack.

Syntax:

VM_RPN
  ; RPN operations here
VM_STOP ; Or VM_SET_INT16, etc., to end the RPN block

VM_RPN itself takes no arguments. The operations within the RPN block implicitly act on the stack.

Usage Example: Calculating Damage with Multiple Factors

Imagine a damage calculation: (PLAYER_ATTACK + WEAPON_BONUS) - ENEMY_DEFENSE. All these values are stored in variables.

; In your combat script:

; Variables
VAR_PLAYER_ATTACK:
  .R_INT16 10
VAR_WEAPON_BONUS:
  .R_INT16 5
VAR_ENEMY_DEFENSE:
  .R_INT16 8
VAR_FINAL_DAMAGE:
  .R_INT16 0 ; To store the result

; Calculate (PLAYER_ATTACK + WEAPON_BONUS) - ENEMY_DEFENSE
VM_PUSH_REFERENCE VAR_FINAL_DAMAGE ; Push reference for where to store the result
VM_RPN
  .R_REF_MEM .R_INT16, VAR_PLAYER_ATTACK   ; Push value of Player Attack (10)
  .R_REF_MEM .R_INT16, VAR_WEAPON_BONUS    ; Push value of Weapon Bonus (5)
  .R_OPERATOR +                           ; Add them (10 + 5 = 15). Stack: [15]
  .R_REF_MEM .R_INT16, VAR_ENEMY_DEFENSE   ; Push value of Enemy Defense (8). Stack: [15, 8]
  .R_OPERATOR -                           ; Subtract (15 - 8 = 7). Stack: [7]
  .R_INT16                                ; Specify result as 16-bit integer
  .R_REF_SET_IND                          ; Store the result (7) into VAR_FINAL_DAMAGE
VM_STOP

; Now VAR_FINAL_DAMAGE will contain 7.
; ... continue script with damage application ...

In this example:

  1. VM_PUSH_REFERENCE VAR_FINAL_DAMAGE prepares the stack for storing the final result.
  2. VM_RPN begins the RPN calculation.
  3. Values are pushed onto the stack (10, then 5).
  4. .R_OPERATOR + pops 5 and 10, adds them, and pushes 15.
  5. 8 is pushed onto the stack.
  6. .R_OPERATOR - pops 8 and 15, subtracts, and pushes 7.
  7. .R_INT16 ensures the type is correct.
  8. .R_REF_SET_IND uses the VAR_FINAL_DAMAGE reference (pushed earlier) and the 7 (result of RPN) to store 7 into VAR_FINAL_DAMAGE.

Analogy to other programming languages: RPN is like using a scientific calculator where you enter numbers first and then the operation. In traditional programming, you write (A + B) - C. In RPN, it’s A B + C -. While it might seem unusual at first, it’s a very efficient way for a stack-based machine to process expressions.