VerseIsland
Feed Learn Leaderboard Guides Reference Explore Search Docs Verse Library
Sign in
Feed Learn 📖 Codex Leaderboard Guides Reference Explore Search Docs Verse Library
Verse Library › Devices
Browse Verse Library

Library

Devices 634
  • Devices171
  • Triggers & Logic118
  • UI & HUD40
  • Audio39
  • Items & Inventory29
  • Events27
  • Scoring & Objectives25
  • Spawning19
  • Classes & Interfaces18
  • Game Modes17
  • Props & Meshes14
  • Variables & Mutability12
  • Player Management11
  • Modules & Structure10
  • Round Flow8
  • Animation6
  • Concurrency6
  • Functions6
  • Getting Started6
  • Teams & Classes6
  • NPCs & AI5
  • Tutorials5
  • VFX & Particles5
  • Arrays & Maps4
  • Cameras4
  • Debugging4
  • Control Flow3
  • Cinematics2
  • Other2
  • Persistence2
  • Scene Graph2
  • Structs & Enums2
  • Building1
  • Physics1
  • Publishing & Islands1
  • Syntax & Types1
  • Vehicles1
  • Weapons1
Verse Language 257
  • Control Flow35
  • Functions26
  • Arrays & Maps25
  • Classes & Interfaces22
  • Variables & Mutability22
  • Concurrency21
  • Syntax & Types18
  • Modules & Structure12
  • Debugging8
  • Devices8
  • Events7
  • Player Management6
  • Structs & Enums6
  • Triggers & Logic6
  • Game Modes5
  • Failure & Options4
  • Scene Graph4
  • UI & HUD4
  • Getting Started3
  • Round Flow3
  • Spawning3
  • VFX & Particles3
  • Reference2
  • Animation1
  • Best Practices1
  • Other1
  • Props & Meshes1
Materials/VFX 154
  • Triggers & Logic27
  • UI & HUD17
  • Devices16
  • VFX & Particles14
  • Props & Meshes11
  • Scoring & Objectives9
  • Game Modes7
  • Items & Inventory7
  • Functions6
  • Arrays & Maps5
  • Animation3
  • Cinematics3
  • Classes & Interfaces3
  • Control Flow3
  • Events3
  • Modules & Structure3
  • Round Flow3
  • Spawning3
  • Getting Started2
  • Scene Graph2
  • Variables & Mutability2
  • Concurrency1
  • Persistence1
  • Player Management1
  • Structs & Enums1
  • Syntax & Types1
General 153
  • Devices22
  • Events20
  • Triggers & Logic20
  • Classes & Interfaces10
  • Variables & Mutability8
  • Round Flow6
  • Scoring & Objectives6
  • UI & HUD6
  • Functions5
  • Player Management5
  • Game Modes4
  • Getting Started4
  • Props & Meshes4
  • Control Flow3
  • Syntax & Types3
  • VFX & Particles3
  • Arrays & Maps2
  • Best Practices2
  • NPCs & AI2
  • Other2
  • Physics2
  • Scene Graph2
  • Spawning2
  • Structs & Enums2
  • Tutorials2
  • Building1
  • Cameras1
  • Cinematics1
  • Failure & Options1
  • Items & Inventory1
  • Teams & Classes1
Player 133
  • Player Management22
  • Teams & Classes19
  • Classes & Interfaces12
  • Devices11
  • Events9
  • Persistence7
  • Triggers & Logic7
  • Arrays & Maps6
  • Functions4
  • Game Modes4
  • Items & Inventory4
  • Round Flow4
  • Debugging3
  • Getting Started3
  • Modules & Structure3
  • Concurrency2
  • Control Flow2
  • Scoring & Objectives2
  • Spawning2
  • Structs & Enums2
  • Physics1
  • Props & Meshes1
  • UI & HUD1
  • Variables & Mutability1
  • Weapons1
Building & Props 131
  • Variables & Mutability15
  • Props & Meshes14
  • Triggers & Logic12
  • Classes & Interfaces10
  • Devices10
  • UI & HUD10
  • Events7
  • Teams & Classes7
  • Animation5
  • Building5
  • Functions5
  • VFX & Particles5
  • Structs & Enums4
  • Control Flow3
  • Game Modes3
  • Items & Inventory3
  • Round Flow3
  • Scene Graph3
  • Arrays & Maps2
  • Concurrency2
  • Reference2
  • Modules & Structure1
NPCs & AI 76
  • NPCs & AI35
  • Spawning7
  • Animation5
  • Variables & Mutability5
  • Classes & Interfaces3
  • Debugging3
  • UI & HUD3
  • Audio2
  • Concurrency2
  • Game Modes2
  • Props & Meshes2
  • Triggers & Logic2
  • Devices1
  • Functions1
  • Getting Started1
  • Reference1
  • VFX & Particles1
Spawning 73
  • Spawning31
  • Events7
  • Concurrency6
  • Player Management6
  • Vehicles5
  • Props & Meshes4
  • Devices3
  • Scene Graph3
  • Items & Inventory2
  • Teams & Classes2
  • Control Flow1
  • Publishing & Islands1
  • Reference1
  • Scoring & Objectives1
Cinematics 71
  • Cameras19
  • Cinematics15
  • Devices11
  • Audio5
  • Animation4
  • Triggers & Logic4
  • Functions2
  • Game Modes2
  • UI & HUD2
  • Classes & Interfaces1
  • Concurrency1
  • Control Flow1
  • Items & Inventory1
  • Modules & Structure1
  • Scene Graph1
  • Templates1
UI 57
  • UI & HUD35
  • Devices5
  • Scoring & Objectives4
  • Classes & Interfaces3
  • Round Flow2
  • Scene Graph2
  • Arrays & Maps1
  • Props & Meshes1
  • Structs & Enums1
  • Templates1
  • Triggers & Logic1
  • Variables & Mutability1
Scene Graph 40
  • Scene Graph9
  • Items & Inventory8
  • Classes & Interfaces3
  • Events3
  • Props & Meshes3
  • Functions2
  • Arrays & Maps1
  • Building1
  • Control Flow1
  • Debugging1
  • Modules & Structure1
  • Player Management1
  • Reference1
  • Structs & Enums1
  • Syntax & Types1
  • Triggers & Logic1
  • UI & HUD1
  • VFX & Particles1
Vehicles 38
  • Spawning11
  • Devices7
  • Vehicles7
  • Props & Meshes4
  • Functions2
  • Game Modes2
  • Failure & Options1
  • Items & Inventory1
  • Reference1
  • Teams & Classes1
  • Tutorials1
Tutorials 37
  • Game Modes6
  • Triggers & Logic5
  • Classes & Interfaces4
  • Events4
  • Props & Meshes3
  • Building2
  • Devices2
  • Items & Inventory2
  • Scoring & Objectives2
  • Animation1
  • Arrays & Maps1
  • Cameras1
  • Concurrency1
  • Physics1
  • Player Management1
  • Structs & Enums1
Weapons 30
  • Game Modes6
  • Weapons6
  • Devices5
  • Items & Inventory3
  • Scoring & Objectives3
  • Spawning2
  • Teams & Classes2
  • Best Practices1
  • Functions1
  • Triggers & Logic1
Items 28
  • Items & Inventory23
  • Devices2
  • Triggers & Logic2
  • Spawning1
Assets 20
  • Modules & Structure6
  • Arrays & Maps3
  • Functions3
  • Scene Graph2
  • Best Practices1
  • Devices1
  • Events1
  • Failure & Options1
  • Physics1
  • Variables & Mutability1
Animation 19
  • Animation10
  • Variables & Mutability4
  • Devices1
  • Player Management1
  • Props & Meshes1
  • Scene Graph1
  • Syntax & Types1
Release Notes 17
  • Classes & Interfaces5
  • Modules & Structure3
  • Concurrency2
  • Control Flow2
  • Variables & Mutability2
  • Debugging1
  • Devices1
  • Items & Inventory1
Input & Controls 16
  • Functions4
  • UI & HUD3
  • Control Flow2
  • Animation1
  • Arrays & Maps1
  • Cinematics1
  • Debugging1
  • Devices1
  • Events1
  • Items & Inventory1
Publishing 8
  • Control Flow5
  • Arrays & Maps1
  • Devices1
  • Syntax & Types1
Audio 7
  • Audio5
  • UI & HUD2
Landscape 7
  • Other4
  • VFX & Particles2
  • Scene Graph1
Persistence 6
  • Structs & Enums2
  • Items & Inventory1
  • Persistence1
  • Publishing & Islands1
  • Variables & Mutability1
Physics 5
  • Functions2
  • Classes & Interfaces1
  • Devices1
  • Syntax & Types1
Creator Economy 3
  • Publishing & Islands2
  • Modules & Structure1
Discovery 3
  • Devices1
  • NPCs & AI1
  • Structs & Enums1
Editor & Project 3
  • Other1
  • Props & Meshes1
  • Tutorials1

Big Numbers Module and Demo Device

Module — 3 files
These files compile together (same module folder).
file_1.verse
# ===============================================================================
# BigNum Module - Scientific Notation Big Number Implementation
# ===============================================================================
#
# Author: VukeFN
# 
# Based on the original work by CeleryMan from Epic Games Community Forums:
# https://dev.epicgames.com/community/snippets/wpbL/fortnite-functions-to-work-with-ridiculously-big-numbers
# 
# Extended and enhanced with additional features including:
# - Enhanced error handling and edge case management
# - Comprehensive comparison operators with abbreviated forms
# - Improved string formatting with negative number support
# - Robust normalization functions for display formatting
# - Comprehensive documentation and code organization
# 
# This module provides a big number system using scientific notation representation.
# Numbers are stored as Value × 10^Exponent where Value is typically 1.0-9.999...
# 
# Features:
# - Arithmetic operations (+, -, *, /)
# - Comparison operations (=, ≠, <, >, ≤, ≥)
# - String formatting with K/M/B/T suffixes
# - Game utility functions for cost calculations
# - Support for very large numbers (up to ~10^308)
# 
# Examples:
# - 1,500 = big_number{Value := 1.5, Exponent := 3}
# - 2.5M = big_number{Value := 2.5, Exponent := 6}
# - 999.9B = big_number{Value := 9.999, Exponent := 11}
# ===============================================================================

using { /Verse.org/Simulation }

BigNum<public> := module:

    # ===========================================================================
    # Core Data Structure
    # ===========================================================================
    
    # Represents a big number using scientific notation: Value × 10^Exponent
    # Value: The significant digits (typically normalized to 1.0-9.999...)
    # Exponent: The power of 10 multiplier
    big_number<public> := struct<concrete><persistable>:
        @editable
        Value:float = 0.0
        @editable  
        Exponent:int = 0

    # ===========================================================================
    # Arithmetic Operators
    # ===========================================================================
    
    # Adds two big_numbers together
    # Aligns exponents to common base before performing addition
    # Result is automatically normalized
    operator'+'<public>(NumberA:big_number, NumberB:big_number)<transacts>:big_number=
        CommonExponent:int = Max(NumberA.Exponent, NumberB.Exponent)

        NewValue:float = (NumberA.Value * Pow(10.0, (NumberA.Exponent - CommonExponent) * 1.0)) + 
                            (NumberB.Value * Pow(10.0, (NumberB.Exponent - CommonExponent) * 1.0))

        Normalize(big_number{Value := NewValue, Exponent := CommonExponent})

    # Subtracts NumberB from NumberA
    # Aligns exponents to common base before performing subtraction
    # Result is automatically normalized
    operator'-'<public>(NumberA:big_number, NumberB:big_number)<transacts>:big_number=
        CommonExponent:int = Max(NumberA.Exponent, NumberB.Exponent)

        NewValue:float = (NumberA.Value * Pow(10.0, (NumberA.Exponent - CommonExponent) * 1.0)) - 
                            (NumberB.Value * Pow(10.0, (NumberB.Exponent - CommonExponent) * 1.0))

        Normalize(big_number{Value := NewValue, Exponent := CommonExponent})

    # Multiplies two big_numbers together
    # Values are multiplied and exponents are added
    # Result is automatically normalized
    operator'*'<public>(NumberA:big_number, NumberB:big_number)<transacts>:big_number=
        NewValue := NumberA.Value * NumberB.Value
        NewExponent := NumberA.Exponent + NumberB.Exponent

        Normalize(big_number{Value := NewValue, Exponent := NewExponent})

    # Multiplies a big_number by a regular float
    # Only the value is scaled, exponent remains the same
    # Result is automatically normalized
    operator'*'<public>(NumberA:big_number, NumberB:float)<transacts>:big_number=
        NewValue := NumberA.Value * NumberB
        NewExponent := NumberA.Exponent

        Normalize(big_number{Value := NewValue, Exponent := NewExponent})

    # Divides NumberA by NumberB
    # Values are divided and exponents are subtracted
    # Returns very large number (10^308) for division by zero
    operator'/'<public>(NumberA:big_number, NumberB:big_number)<transacts>:big_number=
        if (NumberB.Value = 0.0 or (Abs(NumberB.Value) < 1e-15 and NumberB.Exponent <= 0)):
            return big_number{Value := 1.0, Exponent := 308} 
        
        NewValue := NumberA.Value / NumberB.Value
        NewExponent := NumberA.Exponent - NumberB.Exponent
        
        Normalize(big_number{Value := NewValue, Exponent := NewExponent})

    # Divides a big_number by a regular float
    # Only the value is scaled, exponent remains the same
    # Returns very large number (10^308) for division by zero
    operator'/'<public>(NumberA:big_number, NumberB:float)<transacts>:big_number=
        if (NumberB = 0.0 or Abs(NumberB) < 1e-15):
            return big_number{Value := 1.0, Exponent := 308}
        
        NewValue := NumberA.Value / NumberB
        NewExponent := NumberA.Exponent
        
        Normalize(big_number{Value := NewValue, Exponent := NewExponent})

    # ===========================================================================
    # Comparison Functions
    # ===========================================================================
    
    # Returns true if NumberA equals NumberB exactly
    # Both value and exponent must match
    (NumberA:big_number).Equals<public>(NumberB:big_number)<transacts><decides>:void=
        NumberA.Exponent = NumberB.Exponent and NumberA.Value = NumberB.Value

    # Returns true if NumberA does not equal NumberB
    # Inverse of Equals function
    (NumberA:big_number).NotEquals<public>(NumberB:big_number)<transacts><decides>:void=
        not (NumberA.Exponent = NumberB.Exponent and NumberA.Value = NumberB.Value)

    # Returns true if NumberA is greater than NumberB
    # First compares exponents, then values if exponents are equal
    (NumberA:big_number).GreaterThan<public>(NumberB:big_number)<transacts><decides>:void=
        not NumberA.LessThan[NumberB] and not NumberA.Equals[NumberB]

    # Returns true if NumberA is greater than or equal to NumberB
    # First compares exponents, then values if exponents are equal
    (NumberA:big_number).GreaterThanOrEquals<public>(NumberB:big_number)<transacts><decides>:void=
        NumberA.Exponent > NumberB.Exponent or (NumberA.Exponent = NumberB.Exponent and NumberA.Value >= NumberB.Value)

    # Returns true if NumberA is less than NumberB
    # First compares exponents, then values if exponents are equal
    (NumberA:big_number).LessThan<public>(NumberB:big_number)<transacts><decides>:void=
        NumberA.Exponent < NumberB.Exponent or (NumberA.Exponent = NumberB.Exponent and NumberA.Value < NumberB.Value)

    # Returns true if NumberA is less than or equal to NumberB
    # First compares exponents, then values if exponents are equal
    (NumberA:big_number).LessThanOrEquals<public>(NumberB:big_number)<transacts><decides>:void=
        NumberA.Exponent < NumberB.Exponent or (NumberA.Exponent = NumberB.Exponent and NumberA.Value <= NumberB.Value)

    # ===========================================================================
    # Abbreviated Comparison Functions
    # ===========================================================================
    
    # Short aliases for comparison functions for convenience
    (NumberA:big_number).EQ<public>(NumberB:big_number)<transacts><decides>:void= NumberA.Equals[NumberB]
    (NumberA:big_number).NEQ<public>(NumberB:big_number)<transacts><decides>:void= NumberA.NotEquals[NumberB]
    (NumberA:big_number).GT<public>(NumberB:big_number)<transacts><decides>:void= NumberA.GreaterThan[NumberB]
    (NumberA:big_number).GTE<public>(NumberB:big_number)<transacts><decides>:void= NumberA.GreaterThanOrEquals[NumberB]
    (NumberA:big_number).LT<public>(NumberB:big_number)<transacts><decides>:void= NumberA.LessThan[NumberB]
    (NumberA:big_number).LTE<public>(NumberB:big_number)<transacts><decides>:void= NumberA.LessThanOrEquals[NumberB]

    # ===========================================================================
    # Game Utility Functions
    # ===========================================================================

    # Calculates the total cost for purchasing a range of items with scaling prices
    # 
    # Parameters:
    # - BaseCost: The base cost for the first item
    # - Start: Current number of items owned (starting point for price calculation)
    # - Count: Number of items to purchase
    # - CommonRatio: Price scaling factor (1.0 = no scaling, >1.0 = increasing prices)
    # 
    # Returns: Total cost to purchase Count items starting from Start position
    # 
    # Example: If you own 5 items and want to buy 3 more with 1.5x scaling:
    # CalculateCostRange(BaseCost, 5, 3, 1.5) = cost for items 6, 7, and 8
    CalculateCostRange<public>(BaseCost:big_number, Start:int, Count:int, CommonRatio:float)<transacts>:big_number=
        # Handle no scaling case (CommonRatio = 1.0)
        var TotalCost_Value:float = 0.0
        var TotalCost_Exponent:int = 0
        if (CommonRatio = 1.0):
            set TotalCost_Value = BaseCost.Value * Count * 1.0
            set TotalCost_Exponent = BaseCost.Exponent
            return Normalize(big_number{Value := TotalCost_Value, Exponent := TotalCost_Exponent})

        # Geometric series calculation for scaling prices
        # Sum = BaseCost * (ratio^(Start+Count) - ratio^Start) / (ratio - 1)
        term1 := Pow(CommonRatio, (Start + Count) * 1.0)
        term2 := Pow(CommonRatio, Start * 1.0)

        set TotalCost_Value = BaseCost.Value * (term1 - term2) / (CommonRatio - 1.0)
        set TotalCost_Exponent = BaseCost.Exponent

        Normalize(big_number{Value := TotalCost_Value, Exponent := TotalCost_Exponent})

    # Calculates how many items can be afforded with available money
    # 
    # Parameters:
    # - CurrentMoney: Available funds
    # - BaseCost: Base cost per item
    # - AmountOwned: Current number of items owned (affects scaling calculation)
    # - CommonRatio: Price scaling factor (1.0 = no scaling, >1.0 = increasing prices)
    # 
    # Returns: Maximum number of items that can be purchased
    # 
    # Example: With 1000 coins, base cost 100, owning 0 items, no scaling:
    # CalculateAffordableItems(1000, 100, 0, 1.0) = 10 items
    CalculateAffordableItems<public>(CurrentMoney:big_number, BaseCost:big_number, AmountOwned:int, CommonRatio:float)<transacts>:int=
        var AffordableItems:int = 1
        loop:
            if:
                not CurrentMoney.GreaterThanOrEquals[CalculateCostRange(BaseCost, AmountOwned, AffordableItems, CommonRatio)]
            then:
                break
            
            set AffordableItems += 1

        return AffordableItems - 1

    # ===========================================================================
    # String Formatting
    # ===========================================================================

    # Converts a big_number to a human-readable string with appropriate suffixes
    # 
    # Format examples:
    # - 0 → "0"
    # - 123 → "123"
    # - 1,500 → "1.50K"
    # - 2,300,000 → "2.30M"
    # - -1,500 → "-1.50K"
    # - Very large numbers → "1.50e500"
    ToString<public>(ValueIN:big_number):string=
        if (ValueIN.Value = 0.0):
            return "0"

        CorrectedNumber := NormalizeToNearestNumberSet(ValueIN)
        var IsNegative:logic = if(CorrectedNumber.Value < 0.0) then true else false
        
        # Handle small numbers (less than 1000) without suffixes
        if:
            CorrectedNumber.Exponent < 3
            ValueAsInt := Floor[Abs(CorrectedNumber.Value)]
        then:
            return if (IsNegative?) then "-{ValueAsInt}" else "{ValueAsInt}"
        
        # Format larger numbers with suffixes
        var ValueAsString:string = "{Abs(CorrectedNumber.Value)}"

        # Determine precision based on magnitude
        var TargetLength:int = 4  # Default: "1.50" (4 characters)
        if (Abs(CorrectedNumber.Value) >= 100.0):
            set TargetLength = 3  # For "150" (3 characters)

        # Truncate to appropriate length
        if (ValueAsString.Length > TargetLength):
            if:
                Removed := ValueAsString.Remove[TargetLength, ValueAsString.Length]
            then:
                set ValueAsString = Removed
        
        # Add appropriate suffix or scientific notation
        if:
            SuffixIndex:int = Quotient[CorrectedNumber.Exponent, 3]
            SuffixIndex < NumberSuffixes.Length
            Suffix := NumberSuffixes[SuffixIndex]
        then:
            set ValueAsString += Suffix
        else:
            # Fall back to scientific notation for very large numbers
            set ValueAsString += "e{CorrectedNumber.Exponent}"

        if (IsNegative?) then "-{ValueAsString}" else ValueAsString

    # Suffix array for number formatting
    # Each index represents groups of 3 exponent digits (thousands, millions, etc.)
    # Source: https://simple.wikipedia.org/wiki/Names_of_large_numbers
    NumberSuffixes:[]string = array:
        "",      # 10^0   - one
        "K",     # 10^3   - thousand
        "M",     # 10^6   - million  
        "B",     # 10^9   - billion
        "T",     # 10^12  - trillion
        "Qa",    # 10^15  - quadrillion
        "Qi",    # 10^18  - quintillion
        "Sx",    # 10^21  - sextillion
        "Sp",    # 10^24  - septillion
        "Oc",    # 10^27  - octillion
        "No",    # 10^30  - nonillion
        "De",    # 10^33  - decillion
        "Un",    # 10^36  - undecillion
        "Du",    # 10^39  - duodecillion
        "Tr",    # 10^42  - tredecillion
        "Qat",   # 10^45  - quattuordecillion
        "Qin",   # 10^48  - quindecillion
        "Sxt",   # 10^51  - sexdecillion
        "Spt",   # 10^54  - septendecillion
        "Oct",   # 10^57  - octodecillion
        "Non",   # 10^60  - novemdecillion
        "Vig",   # 10^63  - vigintillion
        "Und",   # 10^66  - unvigintillion
        "Duv",   # 10^69  - duovigintillion
        "Trv",   # 10^72  - trevigintillion
        "Qav",   # 10^75  - quattuorvigintillion
        "Qiv",   # 10^78  - quinvigintillion
        "Sxv",   # 10^81  - sexvigintillion
        "Spv",   # 10^84  - septenvigintillion
        "Ocv",   # 10^87  - octovigintillion
        "Nov",   # 10^90  - novemvigintillion
        "Tri",   # 10^93  - trigintillion
        "Utr",   # 10^96  - untrigintillion
        "Dtr",   # 10^99  - duotrigintillion
        "Ttr",   # 10^102 - tretrigintillion
        "Qtr",   # 10^105 - quattuortrigintillion
        "Qntr",  # 10^108 - quintrigintillion
        "Sxtr",  # 10^111 - sextrigintillion
        "Str",   # 10^114 - septentrigintillion
        "Otr",   # 10^117 - octotrigintillion
        "Ntr",   # 10^120 - novemtrigintillion
        "Qua",   # 10^123 - quadragintillion
        "Uqu",   # 10^126 - unquadragintillion
        "Dqu",   # 10^129 - duoquadragintillion
        "Tqu",   # 10^132 - trequadragintillion
        "Qqu",   # 10^135 - quattuorquadragintillion
        "Qnqu",  # 10^138 - quinquadragintillion
        "Squ",   # 10^141 - sexquadragintillion
        "Spqu",  # 10^144 - septenquadragintillion
        "Oqu",   # 10^147 - octoquadragintillion
        "Nqu",   # 10^150 - novemquadragintillion
        "Qui",   # 10^153 - quinquagintillion
        "Uqi",   # 10^156 - unquinquagintillion
        "Dqi",   # 10^159 - duoquinquagintillion
        "Tqi",   # 10^162 - trequinquagintillion
        "Qqi",   # 10^165 - quattuorquinquagintillion
        "Qqui",  # 10^168 - quinquinquagintillion
        "Sqi",   # 10^171 - sexquinquagintillion
        "Spqi",  # 10^174 - septenquinquagintillion
        "
big_number_test.verse
# ===============================================================================
# BigNum Test Suite - Comprehensive Unit Tests for BigNum Module
# ===============================================================================
#
# Author: VukeFN
# 
# Testing Framework Credits:
# Based on the Testing Framework by @RayBenefield
# Source: https://github.com/RayBenefield/dev-xp/tree/master/src/node_modules/%40tableau/testing
# 
# Setup Instructions for UEFN:
# 1. Copy this code into a .verse file in your project
# 2. Build Verse code and place both `test_factory_device` and `big_number_test` devices in your island
# 3. Add the `test_tag` Verse Tag Component to the `big_number_test` device
# 4. Start the game and check the Output Log (bottom left of your UEFN Editor) for test results
# 
# Test Categories:
# - Basic Structure Tests (2 tests)
# - Addition Operations (5 tests)
# - Subtraction Operations (4 tests)
# - Multiplication Operations (5 tests)
# - Division Operations (4 tests)
# - Comparison Functions (7 tests)
# - Normalization Functions (5 tests)
# - Set Normalization (2 tests)
# - String Formatting (7 tests)
# - Game Utility Functions (3 tests)
# 
# Total: 44 comprehensive tests covering all BigNum functionality
# ===============================================================================

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation/Tags }
using { BigNum }

# ===========================================================================
# BigNum Test Suite Class
# ===========================================================================

big_number_test := class(creative_device, test_suite):
    GetName<override>():string = "BigNum"
    GetTests<override>():[]test_case = array:
        # Basic Structure Tests
        test_case:
            Name := "Should create zero big_number by default"
            Test := CreateDefaultZero
        test_case:
            Name := "Should create big_number with custom values"
            Test := CreateCustomValues
        
        # Addition Tests
        test_case:
            Name := "Should add two zero big_numbers"
            Test := AddTwoZeros
        test_case:
            Name := "Should add big_numbers with same exponent"
            Test := AddSameExponent
        test_case:
            Name := "Should add big_numbers with different exponents"
            Test := AddDifferentExponents
        test_case:
            Name := "Should add and normalize to next exponent"
            Test := AddWithNormalization
        test_case:
            Name := "Should add negative numbers"
            Test := AddNegativeNumbers
        
        # Subtraction Tests
        test_case:
            Name := "Should subtract zero"
            Test := SubtractZero
        test_case:
            Name := "Should subtract same exponent"
            Test := SubtractSameExponent
        test_case:
            Name := "Should subtract different exponents"
            Test := SubtractDifferentExponents
        test_case:
            Name := "Should subtract into negative"
            Test := SubtractIntoNegative
        
        # Multiplication Tests
        test_case:
            Name := "Should multiply by one"
            Test := MultiplyByOne
        test_case:
            Name := "Should multiply by zero"
            Test := MultiplyByZero
        test_case:
            Name := "Should multiply two big_numbers"
            Test := MultiplyTwoBigNumbers
        test_case:
            Name := "Should multiply by float"
            Test := MultiplyByFloat
        test_case:
            Name := "Should multiply with normalization"
            Test := MultiplyWithNormalization
        
        # Division Tests
        test_case:
            Name := "Should divide by one"
            Test := DivideByOne
        test_case:
            Name := "Should handle division by zero"
            Test := DivideByZero
        test_case:
            Name := "Should divide two big_numbers"
            Test := DivideTwoBigNumbers
        test_case:
            Name := "Should divide by float"
            Test := DivideByFloat
        
        # Comparison Tests
        test_case:
            Name := "Should detect equal numbers"
            Test := TestEquals
        test_case:
            Name := "Should detect not equal numbers"
            Test := TestNotEquals
        test_case:
            Name := "Should detect greater than"
            Test := TestGreaterThan
        test_case:
            Name := "Should detect greater than or equal"
            Test := TestGreaterThanOrEqual
        test_case:
            Name := "Should detect less than"
            Test := TestLessThan
        test_case:
            Name := "Should detect less than or equal"
            Test := TestLessThanOrEqual
        test_case:
            Name := "Should work with abbreviated comparisons"
            Test := TestAbbreviatedComparisons
        
        # Normalization Tests
        test_case:
            Name := "Should normalize already normalized number"
            Test := NormalizeAlreadyNormalized
        test_case:
            Name := "Should normalize number less than 1"
            Test := NormalizeLessThanOne
        test_case:
            Name := "Should normalize number greater than 10"
            Test := NormalizeGreaterThanTen
        test_case:
            Name := "Should normalize zero to zero"
            Test := NormalizeZero
        test_case:
            Name := "Should normalize negative number"
            Test := NormalizeNegative
        
        # Set Normalization Tests
        test_case:
            Name := "Should set normalize to nearest set"
            Test := SetNormalizeToSet
        test_case:
            Name := "Should not change already set normalized"
            Test := SetNormalizeAlreadySet
        
        # String Formatting Tests
        test_case:
            Name := "Should format zero as string"
            Test := FormatZeroString
        test_case:
            Name := "Should format small numbers"
            Test := FormatSmallNumbers
        test_case:
            Name := "Should format thousands with K suffix"
            Test := FormatThousands
        test_case:
            Name := "Should format millions with M suffix"
            Test := FormatMillions
        test_case:
            Name := "Should format large numbers with proper suffixes"
            Test := FormatLargeNumbers
        test_case:
            Name := "Should format negative numbers"
            Test := FormatNegativeNumbers
        test_case:
            Name := "Should fallback to scientific notation for very large"
            Test := FormatVeryLargeNumbers
        
        # Utility Function Tests
        test_case:
            Name := "Should calculate cost range with no scaling"
            Test := CalculateCostRangeNoScaling
        test_case:
            Name := "Should calculate cost range with scaling"
            Test := CalculateCostRangeWithScaling
        test_case:
            Name := "Should calculate affordable items"
            Test := CalculateAffordableItemsTest

    # ===========================================================================
    # Basic Structure Tests
    # ===========================================================================
    
    CreateDefaultZero():?failure =
        # Arrange & Act
        Number := big_number{}

        # Assert
        if (Number.Value <> 0.0) then return fail("Default value should be 0.0")
        if (Number.Exponent <> 0) then return fail("Default exponent should be 0")
        return false

    CreateCustomValues():?failure =
        # Arrange & Act
        Number := big_number{Value := 1.5, Exponent := 3}

        # Assert
        if (Number.Value <> 1.5) then return fail("Value should be 1.5")
        if (Number.Exponent <> 3) then return fail("Exponent should be 3")
        return false

    # ===========================================================================
    # Addition Tests
    # ===========================================================================
    
    AddTwoZeros():?failure =
        # Arrange
        NumberA := big_number{}
        NumberB := big_number{}

        # Act
        Result := NumberA + NumberB

        # Assert
        if (Result.Value <> 0.0) then return fail("Sum of zeros should be 0")
        if (Result.Exponent <> 0) then return fail("Exponent should be 0")
        return false

    AddSameExponent():?failure =
        # Arrange
        NumberA := big_number{Value := 1.5, Exponent := 3}
        NumberB := big_number{Value := 2.5, Exponent := 3}

        # Act
        Result := NumberA + NumberB

        # Assert
        if (Result.Value <> 4.0) then return fail("Values should add to 4.0")
        if (Result.Exponent <> 3) then return fail("Exponent should remain 3")
        return false

    AddDifferentExponents():?failure =
        # Arrange
        NumberA := big_number{Value := 1.0, Exponent := 3}  # 1000
        NumberB := big_number{Value := 5.0, Exponent := 2}  # 500

        # Act
        Result := NumberA + NumberB

        # Assert
        if (Result.Value <> 1.5) then return fail("Should normalize to 1.5")
        if (Result.Exponent <> 3) then return fail("Should use higher exponent")
        return false

    AddWithNormalization():?failure =
        # Arrange
        NumberA := big_number{Value := 8.0, Exponent := 3}
        NumberB := big_number{Value := 3.0, Exponent := 3}

        # Act
        Result := NumberA + NumberB

        # Assert
        if (Result.Value < 1.0 or Result.Value > 1.2) then return fail("Should normalize to ~1.1")
        if (Result.Exponent <> 4) then return fail("Should increase exponent to 4")
        return false

    AddNegativeNumbers():?failure =
        # Arrange
        NumberA := big_number{Value := -1.5, Exponent := 3}
        NumberB := big_number{Value := -2.5, Exponent := 3}

        # Act
        Result := NumberA + NumberB

        # Assert
        if (Result.Value <> -4.0) then return fail("Negative numbers should add to -4.0")
        return false

    # ===========================================================================
    # Subtraction Tests
    # ===========================================================================
    
    SubtractZero():?failure =
        # Arrange
        NumberA := big_number{Value := 1.5, Exponent := 3}
        NumberB := big_number{}

        # Act
        Result := NumberA - NumberB

        # Assert
        if (Result.Value <> 1.5) then return fail("Subtracting zero should not change value")
        if (Result.Exponent <> 3) then return fail("Exponent should remain the same")
        return false

    SubtractSameExponent():?failure =
        # Arrange
        NumberA := big_number{Value := 5.0, Exponent := 3}
        NumberB := big_number{Value := 2.0, Exponent := 3}

        # Act
        Result := NumberA - NumberB

        # Assert
        if (Result.Value <> 3.0) then return fail("5 - 2 should equal 3")
        if (Result.Exponent <> 3) then return fail("Exponent should remain 3")
        return false

    SubtractDifferentExponents():?failure =
        # Arrange
        NumberA := big_number{Value := 2.0, Exponent := 3}  # 2000
        NumberB := big_number{Value := 5.0, Exponent := 2}  # 500

        # Act
        Result := NumberA - NumberB

        # Assert
        if (Result.Value <> 1.5) then return fail("2000 - 500 should normalize to 1.5")
        if (Result.Exponent <> 3) then return fail("Should use higher exponent")
        return false

    SubtractIntoNegative():?failure =
        # Arrange
        NumberA := big_number{Value := 1.0, Exponent := 3}
        NumberB := big_number{Value := 2.0, Exponent := 3}

        # Act
        Result := NumberA - NumberB

        # Assert
        if (Result.Value <> -1.0) then return fail("1 - 2 should equal -1")
        return false

    # ===========================================================================
    # Multiplication Tests
    # ===========================================================================
    
    MultiplyByOne():?failure =
        # Arrange
        Number := big_number{Value := 1.5, Exponent := 3}

        # Act
        Result := Number * 1.0

        # Assert
        if (Result.Value <> 1.5) then return fail("Multiplying by 1 should not change value")
        if (Result.Exponent <> 3) then return fail("Exponent should not change")
        return false

    MultiplyByZero():?failure =
        # Arrange
        Number := big_number{Value := 1.5, Exponent := 3}

        # Act
        Result := Number * 0.0

        # Assert
        if (Result.Value <> 0.0) then return fail("Multiplying by 0 should give 0")
        return false

    MultiplyTwoBigNumbers():?failure =
        # Arrange
        NumberA := big_number{Value := 2.0, Exponent := 3}
        NumberB := big_number{Value := 3.0, Exponent := 2}

        # Act
        Result := NumberA * NumberB

        # Assert
        if (Result.Value <> 6.0) then return fail("2 * 3 should equal 6")
        if (Result.Exponent <> 5) then return fail("Exponents should add: 3 + 2 = 5")
        return false

    MultiplyByFloat():?failure =
        # Arrange
        Number := big_number{Value := 2.0, Exponent := 3}

        # Act
        Result := Number * 3.5

        # Assert
        if (Result.Value <> 7.0) then return fail("2 * 3.5 should equal 7")
        if (Result.Exponent <> 3) then return fail("Exponent should remain the same")
        return false

    MultiplyWithNormalization():?failure =
        # Arrange
        Number := big_number{Value := 5.0, Exponent := 3}

        # Act
        Result := Number * 25.0

        # Assert
        if (Result.Value < 1.2 or Result.Value > 1.3) then return fail("Should normalize to ~1.25")
        if (Result.Exponent <> 5) then return fail("Should normalize exponent")
        return false

    # ===========================================================================
    # Division Tests
    # ===========================================================================
    
    DivideByOne():?failure =
        # Arrange
        Number := big_number{Value := 1.5, Exponent := 3}

        # Act
        Result := Number / 1.0

        # Assert
        if (Result.Value <> 1.5) then return fail("Dividing by 1 should not change value")
        if (Result.Exponent <> 3) then return fail("Exponent should not change")
        return false

    DivideByZero():?failure =
        # Arrange
        Number := big_number{Value := 1.5, Exponent := 3}

        # Act
        Result := Number / 0.0

        # Assert
        if (Result.Exponent <> 308) then return fail("Division by zero should return very large number")
        return false

    DivideTwoBigNumbers():?failure =
        # Arrange
        NumberA := big_number{Value := 6.0, Exponent := 5}
        NumberB := big_number{Value := 2.0, Exponent := 3}

        # Act
        Result := NumberA / NumberB

        # Assert
        if (Result.Value <> 3.0) then return fail("6 / 2 should equal 3")
        if (Result.Exponent <> 2) then return fail("Exponents should subtract: 5 - 3 = 2")
        return false

    DivideByFloat():?failure =
        # Arrange
        Number := big_number{Value := 8.0, Exponent := 3}

        # Act
        Result := Number / 2.0

        # Assert
        if (Result.Value <> 4.0) then return fail("8 / 2 should equal 4")
        if (Result.Exponent <> 3) then return fail("Exponent should remain the same")
        return false

    # ===========================================================================
    # Comparison Tests
    # ===========================================================================
    
    TestEquals():?failure =
        # Arrange
        NumberA := big_number{Value := 1.5, Exponent := 3}
        NumberB := big_number{Value := 1.5, Exponent := 3}

        # Act & Assert
        if (not NumberA.Equals[NumberB]) then return fail("Equal numbers should be detected as equal")
        return false

    TestNotEquals():?failure =
        # Arrange
        NumberA := big_number{Value := 1.5, Exponent := 3}
        NumberB := big_number{Value := 2.5, Exponent := 3}

        # Act & Assert
        if (not NumberA.NotEquals[NumberB]) then return fail("Different numbers should be detected as not equal")
        return false

    TestGreaterThan():?failure =
        # Arrange
        NumberA := big_number{Value := 2.0, Exponent := 3}
        NumberB := big_number{Value := 1.0, Exponent := 3}

        # Act & Assert
        if (not NumberA.GreaterThan[NumberB]) then return fail("2 should be greater than 1")
        return false

    TestGreaterThanOrEqual():?failure =
        # Arrange
        NumberA := big_number{Value := 2.0, Exponent := 3}
        NumberB := big_number{Value := 2.0, Exponent := 3}

        # Act & Assert
        if (not NumberA.GreaterThanOrEquals[NumberB]) then return fail("2 should be greater than or equal to 2")
        return false

    TestLessThan():?failure =
        # Arrange
        NumberA := big_number{Value := 1.0, Exponent := 3}
        NumberB := big_number{Value := 2.0, Exponent := 3}

        # Act & Assert
        if (not NumberA.LessThan[NumberB]) then return fail("1 should be less than 2")
        return false

    TestLessThanOrEqual():?failure =
        # Arrange
        NumberA := big_number{Value := 1.0, Exponent := 3}
        NumberB := big_number{Value := 1.0, Exponent := 3}

        # Act & Assert
        if (not NumberA.LessThanOrEquals[NumberB]) then return fail("1 should be less than or equal to 1")
        return false

    TestAbbreviatedComparisons():?failure =
        # Arrange
        NumberA := big_number{Value := 2.0, Exponent := 3}
        NumberB := big_number{Value := 2.0, Exponent := 3}

        # Act & Assert
        if (not NumberA.EQ[NumberB]) then return fail("EQ abbreviation should work")
        if (not NumberA.GTE[NumberB]) then return fail("GTE abbreviation should work")
        if (not NumberA.LTE[NumberB]) then return fail("LTE abbreviation should work")
        return false

    # ===========================================================================
    # Normalization Tests
    # ===========================================================================
    
    NormalizeAlreadyNormalized():?failure =
        # Arrange
        Number := big_number{Value := 1.5, Exponent := 3}

        # Act
        Result := Normalize(Number)

        # Assert
        if (Result.Value <> 1.5) then return fail("Already normalized number should not change")
        if (Result.Exponent <> 3) then return fail("Exponent should not change")
        return false

    NormalizeLessThanOne():?failure =
        # Arrange
        Number := big_number{Value := 0.15, Exponent := 4}

        # Act
        Result := Normalize(Number)

        # Assert
        if (Result.Value <> 1.5) then return fail("Should normalize to 1.5")
        if (Result.Exponent <> 3) then return fail("Should decrease exponent to 3")
        return false

    NormalizeGreaterThanTen():?failure =
        # Arrange
        Number := big_number{Value := 15.0, Exponent := 2}

        # Act
        Result := Normalize(Number)

        # Assert
        if (Result.Value <> 1.5) then return fail("Should normalize to 1.5")
        if (Result.Exponent <> 3) then return fail("Should increase exponent to 3")
        return false

    NormalizeZero():?failure =
        # Arrange
        Number := big_number{Value := 0.0, Exponent := 5}

        # Act
        Result := Normalize(Number)

        # Assert
        if (Result.Value <> 0.0) then return fail("Zero should remain zero")
        if (Result.Exponent <> 0) then return fail("Zero exponent should be 0")
        return false

    NormalizeNegative():?failure =
        # Arrange
        Number := big_number{Value := -15.0, Exponent := 2}

        # Act
        Result := Normalize(Number)

        # Assert
        if (Result.Value <> -1.5) then return fail("Should normalize to -1.5 while preserving sign")
        if (Result.Exponent <> 3) then return fail("Should increase exponent to 3")
        return false

    # ===========================================================================
    # Set Normalization Tests
    # ===========================================================================
    
    SetNormalizeToSet():?failure =
        # Arrange
        Number := big_number{Value := 1.5, Exponent := 4}

        # Act
        Result := NormalizeToNearestNumberSet(Number)

        # Assert
        if (Result.Value <> 15.0) then return fail("Should adjust to 15.0")
        if (Result.Exponent <> 3) then return fail("Should adjust exponent to nearest set (3)")
        return false

    SetNormalizeAlreadySet():?failure =
        # Arrange
        Number := big_number{Value := 15.0, Exponent := 3}

        # Act
        Result := NormalizeToNearestNumberSet(Number)

        # Assert
        if (Result.Value <> 15.0) then return fail("Already set normalized should not change")
        if (Result.Exponent <> 3) then return fail("Exponent should remain 3")
        return false

    # ===========================================================================
    # String Formatting Tests
    # ===========================================================================
    
    FormatZeroString():?failure =
        # Arrange
        Number := big_number{}

        # Act
        Result := ToString(Number)

        # Assert
        if (not Result = "0") then return fail("Zero should format as '0'")
        return false

    FormatSmallNumbers():?failure =
        # Arrange
        Number := big_number{Value := 123.0, Exponent := 0}

        # Act
        Result := ToString(Number)

        # Assert
        if (not Result = "123") then return fail("Small numbers should format without suffix")
        return false

    FormatThousands():?failure =
        # Arrange
        Number := big_number{Value := 1.5, Exponent := 3}

        # Act
        Result := ToString(Number)

        # Assert
        if (not Result = "1.50K") then return fail("Expected '1.50K', got '{Result}'")
        return false

    FormatMillions():?failure =
        # Arrange
        Number := big_number{Value := 2.3, Exponent := 6}

        # Act
        Result := ToString(Number)

        # Assert
        if (not Result = "2.30M") then return fail("Expected '2.30M', got '{Result}'")
        return false


    FormatLargeNumbers():?failure =
        # Arrange
        Number := big_number{Value := 1.5, Exponent := 33}

        # Act
        Result := ToString(Number)

        # Assert
        if (not Result = "1.50De") then return fail("Expected '1.50B', got '{Result}'")
        return false

    FormatNegativeNumbers():?failure =
        # Arrange
        Number := big_number{Value := -1.5, Exponent := 3}

        # Act
        Result := ToString(Number)

        # Assert
        if (not Result = "-1.50K") then return fail("Expected '-1.50K', got '{Result}'")
        return false

    FormatVeryLargeNumbers():?failure =
        # Arrange
        Number := big_number{Value := 1.5, Exponent := 500}

        # Act
        Result := ToString(Number)

        # Assert - Should contain 'e' for scientific notation
        if (Result.Length <= 5) then return fail("Very large numbers should use scientific notation")
        return false

    # ===========================================================================
    # Game Utility Function Tests
    # ===========================================================================
    
    CalculateCostRangeNoScaling():?failure =
        # Arrange
        BaseCost := big_number{Value := 1.0, Exponent := 2}  # 100
        Start := 0
        Count := 5
        CommonRatio := 1.0

        # Act
        Result := CalculateCostRange(BaseCost, Start, Count, CommonRatio)

        # Assert - Should be 5 * 100 = 500
        if (Result.Value <> 5.0) then return fail("Cost with no scaling should be 5 * 100")
        if (Result.Exponent <> 2) then return fail("Exponent should remain 2")
        return false

    CalculateCostRangeWithScaling():?failure =
        # Arrange
        BaseCost := big_number{Value := 1.0, Exponent := 2}  # 100
        Start := 0
        Count := 3
        CommonRatio := 2.0

        # Act
        Result := CalculateCostRange(BaseCost, Start, Count, CommonRatio)

        # Assert
        # Should be 100 * (2^3 - 2^0) / (2 - 1) = 100 * 7 = 700
        if (Result.Value <> 7.0) then return fail("Cost with scaling should calculate geometric series")
        if (Result.Exponent <> 2) then return fail("Base exponent should be maintained")
        return false

    CalculateAffordableItemsTest():?failure =
        # Arrange
        CurrentMoney := big_number{Value := 1.0, Exponent := 3}  # 1000
        BaseCost := big_number{Value := 1.0, Exponent := 2}     # 100
        AmountOwned := 0
        CommonRatio := 1.0

        # Act
        Result := CalculateAffordableItems(CurrentMoney, BaseCost, AmountOwned, CommonRatio)

        # Assert
        if (Result <> 10) then return fail("Should be able to afford 10 items (1000 / 100)")
        return false

# ===========================================================================
# Testing Framework Implementation
# ===========================================================================
# 
# The following section contains the core testing framework infrastructure
# that enables automatic test discovery, execution, and reporting.
# ===========================================================================

# Test factory device that discovers and runs all test suites
test_factory_device := class(creative_device):

    OnBegin<override>()<suspends>:void=
        TestSuites := LoadTestDevices(Self)

        var SuiteResults:[test_suite][]tuple(test_case, ?failure) = map{}
        for(Suite : TestSuites):
            TestCases := Suite.GetTests()
            TestCaseResults := for(TestCase:TestCases). (TestCase, TestCase.Test())
            if(set SuiteResults[Suite] = TestCaseResults) {}

        var PrintResults:string = ""
        var Passes:int = 0
        var Fails:int = 0
        var Total:int = 0
        for(Suite -> Results:SuiteResults):
            set PrintResults += "\n-\n✎ {Suite.GetName()}\n-"

            for(Result : Results):
                TestCase := Result(0)
                MaybeFail := Result(1)
                # (TestCase, MaybeFail) := Result
                if(Fail := MaybeFail?):
                    set Fails += 1
                    set PrintResults += "\n\t❌ {TestCase.Name}\n\t\t➥ {Fail.Msg}"
                else:
                    set Passes += 1
                    set PrintResults += "\n\t✔ {TestCase.Name}"
                set Total += 1

        set PrintResults += "\n-\n ✔ Pass  = {Passes}\n ❌ Fail  = {Fails}\n ➰ Total = {Total}\n-"
        if (TestSuites.Length = 0):
            set PrintResults += "\n➰ NONE\t➰ NONE\t➰ NONE\t➰ NONE\t➰ NONE\t➰\n-"
            set PrintResults += "\n "
        else:
            if (Fails <= 0):
                set PrintResults += "\n✔ PASS\t✔ PASS\t✔ PASS\t✔ PASS\t✔ PASS\t✔\n-"
            else:
                set PrintResults += "\n❌ FAIL\t❌ FAIL\t❌ FAIL\t❌ FAIL\t❌ FAIL\t❌\n-"
        Print(PrintResults)

# Core testing framework types and functions
test_tag<public> := class(tag){}
test := type{_():?failure}
fail<public>(Msg:string)<transacts>:?failure = option. failure. Msg := Msg
failure<public> := struct:
    Msg<public>:string = "Fail"

test_case<public> := class():
    Name<public>:string = "<No Name>"
    Test<public>:test

test_suite<public> := interface<unique>():
    GetName<public>():string
    GetTests<public>():[]test_case

LoadTestDevices<public>(BaseDevice:creative_device):[]test_suite=
    TaggedDevices := BaseDevice.FindCreativeObjectsWithTag(test_tag{})
    for(Index->Tagged:TaggedDevices, Device := test_suite[Tagged]). Device
bignum_demo_device.verse
# ===============================================================================
# BigNum Demo Device - Interactive Demonstration of BigNum Module
# ===============================================================================
#
# Author: VukeFN
# 
# This device provides an interactive way to test and demonstrate the BigNum module
# using button_device controls and hud_message_device display.
# 
# Setup Instructions:
# 1. Place this device on your island
# 2. Place 6 button_device objects near it for the different operations
# 3. Place 1 hud_message_device for displaying the current value
# 4. Configure the device properties to link the buttons and HUD display
# 5. Test the BigNum operations by interacting with the buttons
# 
# Features Demonstrated:
# - Basic arithmetic operations (add, multiply)
# - Large number handling (millions, billions, trillions)
# - String formatting with K/M/B/T suffixes
# - Scientific notation for very large numbers
#
# **Try This Sequence:**
# 1. Add Thousand (several times) → See: 1.00K, 2.00K, 3.00K...
# 2. Add Million → See jump to: 1.00M+
# 3. Multiply by 100 → See: 100M+  
# 4. Add Billion → See: 1.10B+
# 5. Multiply by 10 & 100 repeatedly → Watch it grow to trillions!
# ===============================================================================

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { BigNum }

bignum_demo_device := class(creative_device):
    
    # ===========================================================================
    # Device Configuration - Set these in the UEFN editor
    # ===========================================================================
    
    @editable
    AddThousandButton:button_device = button_device{}
    
    @editable  
    AddMillionButton:button_device = button_device{}
    
    @editable
    MultiplyBy10Button:button_device = button_device{}
    
    @editable
    MultiplyBy100Button:button_device = button_device{}
    
    @editable
    AddBillionButton:button_device = button_device{}
    
    @editable
    ResetButton:button_device = button_device{}
    
    @editable
    DisplayHUD:hud_message_device = hud_message_device{}

    # ===========================================================================
    # Internal State
    # ===========================================================================
    
    var CurrentValue:big_number = big_number{Value := 0.0, Exponent := 0}

    # ===========================================================================
    # Device Lifecycle
    # ===========================================================================
    
    OnBegin<override>()<suspends>:void =
        # Configure button texts and interactions
        SetupButtons()
        
        # Subscribe to button events
        AddThousandButton.InteractedWithEvent.Subscribe(OnAddThousand)
        AddMillionButton.InteractedWithEvent.Subscribe(OnAddMillion)
        MultiplyBy10Button.InteractedWithEvent.Subscribe(OnMultiplyBy10)
        MultiplyBy100Button.InteractedWithEvent.Subscribe(OnMultiplyBy100)
        AddBillionButton.InteractedWithEvent.Subscribe(OnAddBillion)
        ResetButton.InteractedWithEvent.Subscribe(OnReset)
        
        # Show initial value
        UpdateDisplay()

    # ===========================================================================
    # Button Configuration
    # ===========================================================================
    S2M<localizes>(S:string):message="{S}"
    
    SetupButtons():void =
        # Configure button interaction texts
        AddThousandButton.SetInteractionText(S2M("Add 1,000"))
        AddThousandButton.SetInteractionTime(0.1)
        
        AddMillionButton.SetInteractionText(S2M("Add 1 Million"))
        AddMillionButton.SetInteractionTime(0.1)
        
        MultiplyBy10Button.SetInteractionText(S2M("Multiply by 10"))
        MultiplyBy10Button.SetInteractionTime(0.1)
        
        MultiplyBy100Button.SetInteractionText(S2M("Multiply by 100"))
        MultiplyBy100Button.SetInteractionTime(0.1)
        
        AddBillionButton.SetInteractionText(S2M("Add 1 Billion"))
        AddBillionButton.SetInteractionTime(0.1)
        
        ResetButton.SetInteractionText(S2M("Reset to Zero"))
        ResetButton.SetInteractionTime(0.5)  # Longer hold to prevent accidents

    # ===========================================================================
    # Button Event Handlers
    # ===========================================================================
    
    OnAddThousand(Agent:agent):void =
        # Add 1,000 to current value
        ThousandValue := big_number{Value := 1.0, Exponent := 3}
        set CurrentValue = CurrentValue + ThousandValue
        UpdateDisplay()
        
        # Show feedback to the player
        DisplayHUD.Show(Agent, S2M("Added 1,000!"), ?DisplayTime := 2.0)

    OnAddMillion(Agent:agent):void =
        # Add 1,000,000 to current value  
        MillionValue := big_number{Value := 1.0, Exponent := 6}
        set CurrentValue = CurrentValue + MillionValue
        UpdateDisplay()
        
        # Show feedback to the player
        DisplayHUD.Show(Agent, S2M("Added 1 Million!"), ?DisplayTime := 2.0)

    OnMultiplyBy10(Agent:agent):void =
        # Multiply current value by 10
        set CurrentValue = CurrentValue * 10.0
        UpdateDisplay()
        
        # Show feedback to the player
        DisplayHUD.Show(Agent, S2M("Multiplied by 10!"), ?DisplayTime := 2.0)

    OnMultiplyBy100(Agent:agent):void =
        # Multiply current value by 100
        set CurrentValue = CurrentValue * 100.0
        UpdateDisplay()
        
        # Show feedback to the player
        DisplayHUD.Show(Agent, S2M("Multiplied by 100!"), ?DisplayTime := 2.0)

    OnAddBillion(Agent:agent):void =
        # Add 1,000,000,000 to current value
        BillionValue := big_number{Value := 1.0, Exponent := 9}
        set CurrentValue = CurrentValue + BillionValue
        UpdateDisplay()
        
        # Show feedback to the player
        DisplayHUD.Show(Agent, S2M("Added 1 Billion!"), ?DisplayTime := 2.0)

    OnReset(Agent:agent):void =
        # Reset to zero
        set CurrentValue = big_number{Value := 0.0, Exponent := 0}
        UpdateDisplay()
        
        # Show feedback to the player
        DisplayHUD.Show(Agent, S2M("Reset to Zero!"), ?DisplayTime := 2.0)

    # ===========================================================================
    # Display Management
    # ===========================================================================
    
    UpdateDisplay():void =
        # Format the current value and display it
        FormattedValue := ToString(CurrentValue)
        DisplayMessage := "Current Value: {FormattedValue}"
        
        # Set persistent display
        DisplayHUD.SetDisplayTime(0.0)  # Persistent display
        DisplayHUD.Show(S2M(DisplayMessage))
        
        # Also print to console for debugging
        Print("BigNum Demo - Current Value: {FormattedValue}")

    # ===========================================================================
    # Utility Functions for Advanced Testing
    # ===========================================================================
    
    # Call this function to test very large numbers
    TestVeryLargeNumbers():void =
        # Create some massive numbers to test scientific notation
        TestValues := array:
            big_number{Value := 1.5, Exponent := 100}    # 1.5 * 10^100
            big_number{Value := 9.99, Exponent := 500}   # 9.99 * 10^500
            big_number{Value := 2.5, Exponent := 1000}   # 2.5 * 10^1000
        
        for (TestValue : TestValues):
            FormattedValue := ToString(TestValue)
            Print("Test Large Number: {FormattedValue}")

    # Call this function to test arithmetic operations
    TestArithmetic():void =
        # Test some arithmetic operations
        A := big_number{Value := 1.5, Exponent := 6}  # 1.5M
        B := big_number{Value := 2.0, Exponent := 3}  # 2K
        
        Sum := A + B
        Product := A * B
        BNQuotient := A / B
        
        Print("Arithmetic Test:")
        Print("A = {ToString(A)}")
        Print("B = {ToString(B)}")
        Print("A + B = {ToString(Sum)}")
        Print("A * B = {ToString(Product)}")
        Print("A / B = {ToString(BNQuotient)}")

    # Call this function to test comparison operations  
    TestComparisons():void =
        # Test comparison operations
        Small := big_number{Value := 1.0, Exponent := 3}   # 1K
        Large := big_number{Value := 1.0, Exponent := 6}   # 1M
        
        Print("Comparison Test:")
        Print("Small = {ToString(Small)}")
        Print("Large = {ToString(Large)}")
        Print("Small < Large: {if (Small.LT[Large]) then "true" else "false"}")
        Print("Large > Small: {if (Large.GT[Small]) then "true" else "false"}")
        Print("Small == Small: {if (Small.EQ[Small]) then "true" else "false"}")
Sign in to download module

Copy-paste each file above is always free.

Comments

    Sign in to vote, comment, or suggest an edit. Sign in
    📄
    Source
    RayBenefield
    Epic Games Community
    RayBenefield @int

    Created by a member of the Epic Games community. Rights remain with the original author, under Epic's community content terms. Terms ↗

    View original Sources & licensing
    Request removal
    Last updated Jun 23, 2026
    Verse module (3 files)
    Build failed · 1 error

    Download the full module (zip) from the code panel above.

    Keep exploring
    More in Devices · 22 of 60
    Prev
    fortnite waiting for players countdown device
    Next
    fortnite double pump verse device
    Related topics
    • Fortnite Digests Release 24 20 Cl 24939793 Verse Language
    • Fortnite Dbno Revive Infect Device Devices
    • ui Verse Language
    • fortniterarities Items
    • megaitems Items

    Related

    Open in graph →

    Related topics

    • Fortnite Digests Release 24 20 Cl 24939793
    • Fortnite Dbno Revive Infect Device
    • ui
    • fortniterarities
    • megaitems
    VerseIsland · an archipelago of Verse & UEFN knowledge
    🗺️ Island atlas Learn Guides History About & Press Sources & Licensing Status

    Not affiliated with Epic Games. Fortnite, UEFN, Unreal Engine, and Verse are trademarks of Epic Games, Inc. Content is attributed to its source — see Sources & Licensing.

    🦜

    Scout · your island guide

    The Isle of Verse