• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

How To Separate Numbers

Status
Not open for further replies.
Level 33
Joined
Mar 27, 2008
Messages
8,035
You see, if I want "784" to be shown on the screen, I just don't want it to be shown 784, what I want is to separate them such as;
700
80
4

All of these would become 784, right ?

How do I separate these values ?

You see, I'm creating an ability that has over 1000 levels, and it would unefficient to just use 1000 levels of ability directly into the game, right ?
Therefore, I think I should separate the numbers up a bit such as;
There are 9 Levels +1 Bonus Damage
There are 9 Levels of +10 Bonus Damage
There are 9 Levels of +100 Bonus Damage

Simply, if I want to add 458 damage, I would;
First add Level 4 +100 Bonus Damage
Then add Level 5 +10 Bonus Damage
Lastly I would add Level 8 +1 Bonus Damage

Sum it up, (+100 * 4) + (+10 * 5) + (+1 * 8) = +458 Bonus Damage

How can I separate numbers in triggers ?
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
Sum it up, (+100 * 4) + (+10 * 5) + (+1 * 8) = +458 Bonus Damage

You just multiplicated the values here, what is the reverse operation?

784 / 100 = 7 R 84
84 / 10 = 8 R 4
4 / 1 = 4

integer division

The optimal solution to reduce ability levels however would be to take powers of 2.

Your system with 27 abilities allows a max of 999. 2^10 (10+1 abilities) is already 1024 and you would still be able to reach all integer numbers. Of course, this would require logarithm or similar.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
Code:
function ModuloInteger takes integer dividend, integer divisor returns integer
    local integer modulus = dividend - (dividend / divisor) * divisor

    // If the dividend was negative, the above modulus calculation will
    // be negative, but within (-divisor..0).  We can add (divisor) to
    // shift this result into the desired range of (0..divisor).
    if (modulus < 0) then
        set modulus = modulus + divisor
    endif

    return modulus
endfunction

Well, it is practically the same but remultiplicating quotient with divisor and subtracting that from dividend as shown in the first line would be a bit cheaper since we already have the quotient and do not need the lower part with negativity.
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
Okay, found a new problem,
If the number is 874, it's easy, right ?
Because what you said,
784 / 100 = 7 R 84
84 / 10 = 8 R 4
4 / 1 = 4

What if the number contains at least one 0 ?
Such as 804 ?

Okay, at first, I can do this, 804 mod 100 = 04 (4)
But how do I retrieve the '0' in front of 4 ?

The trigger instead returns a value of 4, what I want it returns 0, how do I achieve that ?

Same goes to 820 (0 at behind of the numbers)

And may I ask, does the algorithm will change if we take 4 digit value such as;
8200
8020
8002
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
When you divide this 4 by the next divisor 10, the result is 0. So the level for the ability with bonuses of 10 is 0, which equals zero. That is what you want. You may also specifically ask for this 0 in an if in case it is not automatically covered. So yeah, then you continue to the next divisor 1 with still 4 remaining.

804 / 100 = 8 R 4
4 / 10 = 0 R 4
4 / 1 = 4

8020 / 1000 = 8 R 20
20 / 100 = 0 R 20
20 / 10 = 2 R 0
0 / 1 = 0
 
Level 5
Joined
Jun 16, 2004
Messages
108
You could loop from the back of the number, ends up being cleaner.
In these examples, % means modulo

784 % 10 = 4; your lowest +damage ability level
784 / 10 = 78
78 % 10 = 8; your next +damage ability level
78 / 10 = 7
7 % 10 = 7; etc

Looping backward until the number hits 0

804 % 10 = 4
804 / 10 = 80
80 % 10 = 0
80 / 10 = 8
8 % 10 = 8

820 % 10 = 0
82 % 10 = 2
8 % 10 = 8

Here is some simple code to do just that sort of thing:
JASS:
function looping takes integer value, unit u returns nothing
    local integer array abilities
    local integer pos = 0
    local integer max_value = 9999
    local integer mod
    if (value > max_value) then
        call BJDebugMsg("entered too large of a value")
        return
    endif
    set abilities[0] = 'xxxx' // +0-9
    set abilities[1] = 'xxxx' // +10-90
    set abilities[2] = 'xxxx' // +100-900
    set abilities[3] = 'xxxx' // +1000-9000
    loop
        exitwhen (value == 0)
        
        set mod = ModuloInteger(value, 10)
        call BJDebugMsg("mod = "+I2S(mod))
        if (mod > 0) then
            call BJDebugMsg("Adding ability["+I2S(pos)+"], set to level "+I2S(mod))
            call UnitAddAbility(u, abilities[pos])
            call SetUnitAbilityLevel(u, abilities[pos], mod)
        else
            call BJDebugMsg("modulo was 0, not adding ability")
        endif
        
        set pos = pos + 1
        set value = value / 10
    endloop
endfunction

There exist vJASS libraries to do this sort of thing for you efficiently already, by the way. Such as BonusMod from wc3c (http://www.wc3c.net/showthread.php?t=107940) and probably stuff on the hive as well.
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
Thanks for the input Halo (I did not test it yet, I will)

There exist vJASS libraries to do this sort of thing for you efficiently already, by the way. Such as BonusMod from wc3c (http://www.wc3c.net/showthread.php?t=107940) and probably stuff on the hive as well.
It is because I'm trying to recreate this system in GUI, for GUI users so they do not have to tamper with vJASS or JNGP.
 
Status
Not open for further replies.
Top