Big numbers getting cut

Xialian

Member
Reaction score
8
Hello!

I've been working on a Cookie Clicker clone in the World Editor lately. So far, everything's been running smoothly (with the exception of multiple multiboards active at the same time, but that's a different deal altogether, but I've run into a very strange problem.

The values in the map of course run in Real and Integer variables (because Gold only goes to 1 million, that is), which is fine and easy to work with, but when I reach really high numbers like 100 million, 2 billion and 5 billion, the "income" part will have strange cuts in it. At first it's just a few decimals getting removed, then whole numbers (starts at 4, then goes to 24, 40, 340 and so forth). I can send variables and triggers if needed.

I've heard that WC3 runs on a 32-bit system, at therefor should be able to work with those numbers without any real issues, but I don't know if the engine is the problem. I can't find any info on the issue on the web or mentioned anywhere else, so I was hoping somebody on here knows the answer.

Thanks for your time :)
Xialian
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
Are you talking about floating point arithmetics?
Its very usual that floating point numbers lose more and more precision the bigger they get.

But until you can give us a concrete example I cant really tell you more.
 

Xialian

Member
Reaction score
8
A more concrete example? Hm

If we say I have an "income" of 6300, and that is applied every second to the total amount of "gold" that I own, which is 5 billion, I will only receive 5760, instead of 6300. If I have 250-500 million with the same income, I will receive about 6060 every second.
 

Solu9

You can change this now in User CP.
Reaction score
216
What kind of calculations are you doing?
Are you multiplying reals and then convert them to integers or something else?

Because if you just use integers this problem should not occur I believe.
 

Xialian

Member
Reaction score
8
Trigger:
  • GG Red
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Gold Digger
      • (Owner of (Casting unit)) Equal to Player 1 (Red)
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • RedGold Greater than or equal to GGCost[0]
        • Then - Actions
          • Set GGIncomeBase[0] = (GGIncomeBase[0] + GGWorth[0])
          • Set RedGold = (RedGold - (Real((Integer(GGCost[0])))))
          • Set GGCost[0] = (GGCost[0] x 1.15)
          • Set GGIncomeFinal[0] = (GGIncomeBase[0] x (Real(GGMultiplier[0])))
          • Set GGAmount[0] = (GGAmount[0] + 1)
        • Else - Actions
          • Game - Display to PGRed for 3.00 seconds the text: Not enough gold!

GGIncomeBase is a real
RedGold is a real
GGCost is a real, then converted to a integer on the scoreboard, but that's not important
GGIncomeFinal is a real
GGAmount is an integer

That's just one of the buildings in the map. The income goes like this:
Trigger:
  • Income Add
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • -------- Currency Update --------
      • Trigger - Run Value Updates <gen> (ignoring conditions)
      • Set RedGold = (RedGold + TotalIncome[0])
      • Set BlueGold = (BlueGold + TotalIncome[1])
      • Set TealGold = (TealGold + TotalIncome[2])
      • Set PurpleGold = (PurpleGold + TotalIncome[3])
    • Value Updates
      • Events
      • Conditions
      • Actions
        • Set IncomeBase[0] = (GGIncomeFinal[0] + (GTIncomeFinal[0] + (GDIncomeFinal[0] + (SVIncomeFinal[0] + (FSIncomeFinal[0] + (GHIncomeBase[0] + 0.00))))))
        • Set TotalIncome[0] = (IncomeBase[0] x IncomeMultiplier[0])

I hope my use of the WC3 tags don't bother to much :)
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
Well, theres lots of floating point arithmetic right there. Its no suprise to me it doesnt work quite right.
I dont know exactly what kind of floats they are using in wc3, but its probably not precise enough for the numbers you are using.
Either go with smaller numbers or use integers for your arithmetic.
 

Solu9

You can change this now in User CP.
Reaction score
216
Puh I can't find the exact problem without real numbers.
But the problem sure lies somewhere in your conversion from integer to real and back.
 

Xialian

Member
Reaction score
8
You may be right, Accname. I guess the game isn't fit for this kind of thing. I was just a fun thing to do, when all of your friends play the game AND CC, which made the idea exciting.

Solu9, the numbers I'm referring to in this post aren't converted at any time, just to avoid any bugs ;)

I can also upload the map if you want to see the "bug" yourselves.

Edit: I might try to make the Gold an integer. Will post results.
Ninja Edit: Worked better - nothing got lost, but when I reached 2 billion, it instantly went to -2 billion for some reason.
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
Just why do you want to go up to such high numbers?
I bet you could do the same game and stay with number far lower and more precise.
But of course, using integers is always the safer solution. If you need numbers behind the floating point you might always try to emulate fixed-point arithmetics with integers.
 

Xialian

Member
Reaction score
8
That's the point behind incremental games - to see your numbers grow (this is so addicting, please help), and that's fun. I could probably make it lower, but I'm not sure how.
What do you mean by fixed-point arithmetics? It sounds interesting.
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
Fixed point arithmetic has a fixed number of digits after the floating point. In comparison to floating point arithmetic which has an (more or less) arbitrary number of digits after the floating point.
The benefit of fixed point arithmetic is that its as precise as integer arithmetic because you can simulate it with integers.

int 0 == fixpoint 0
int 500 == fixpoint 0.5
int 758 == fixpoint 0.758
int 1366 == fixpoint 1.366
int 53236 == fixpoint 53.236
etc

Basically you multiply your number by a fixed factor to transform it into an integer. If you multiply by 10 you have 1 digit behind the decimal point; multiplying by 100 gives you 2 digits, by 1000 gives you 3 digits, etc.
Of course there are a few little obstacles when multiplying and dividing fixpoint numbers, but I guess you can figure that out on your own or through the use of the internatz.
 

Xialian

Member
Reaction score
8
I don't quite get it. I may be dumb and tired, though.
On another point: I've been thinking about just dividing every 1 million or something. Then it would look something like this:
1.000.000 -> Number is divided by 1 million or 1000 or something and will be 1M or 1000k, just to make it manageable and easier for the computer to calculate, and that could of course just continue. I don't know how to make it handle that with prices on the buildings, but I might find out something.

By the way; so far, the info I've gotten about the float arithmetics and so forth has been really enlightening - thank you so much!
 

Xialian

Member
Reaction score
8
Sorry for disturbing you people again, but I just started looking up Fixed-point arithmetics after a short break, and I don't quite get how to make it work in WC3, or just anywhere at all. Could you please provide an example of how it's done? I would be very grateful, and might even be able to finish my project(s).
 

Accname

2D-Graphics enthusiast
Reaction score
1,462
First you choose how many digits you want to have behind the floating point, then you take 10 to the power of your number of digits and call that f.
For 2 digits behind the floating point you get 10² == 100 == f.
For 3 digits behind the floating point you get 10³ == 1000 == f.

Now you can transform any integer into a fixpoint number with your choosen precision.
If you want the integer A to become a fixpoint number you do:
A *= f
If you want the fixpoint number B to become an integer you do:
B /= f (digits behind the floating point will be lost when converting)

If you have a fixpoint number A and you want to get the digits before the floating point (lets call them major digits) and the digits after the floating point (minor digits) you do the following:
major = A / f
minor = A mod f (mod == modulo function)

If you have the fixpoint numbers A and B you can do simple arithmetics like this:
A + B == A + B
A - B == A - B
A mod B == A mod B
A * B == A * (B / f)
A / B == A / (B / f)

The result will be a fixpoint.

If you have a fixpoint A and a float / integer B you can do simple arithmetics like this:
A + B == A + (B * f)
A - B == A - (B * f)
A mod B == A mod (B * f)
A * B == A * B
A / B == A / B

The result will be a fixpoint.


I hope this covers enough of the theory for you.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top