I am writing the multiplayer server for my current game in Ruby using Sinatra. Since it is turn based and not particularly performance heavy, this is not a problem. One of the cardinal rules of making a multiplayer game is don’t trust the client.
This means I needed to write the game logic for the game on the server.
Modulo
Part of the game logic involves taking an angle and a position and calculating a new position and angle based of a units performance stats. In order to simplify the math, I wanted to keep all the angles positive.
So if the angle is negative, I Mod it by 360 and then add 360.
If the angle is positive, I just Mod it by 360.
But then I change it either adding a units turn rate to it or subtracting the turn rate from it.
The client (written in Monkey-X) was working 100% as expected. But the server was giving me some weird results.
Negative Numbers Behave Differently
I have always understood Mod, often the %
operator in language, to return the remainder from a division operation. And that is what it is supposed to do. In Monkey-X that is exactly what it does (incidentally it is the word ‘Mod’ in Monkey-X). And in Ruby, all of my positive angles where behaving as expected.
But for negative numbers in Ruby, something like:
-21 % 5
is not going to return -1, it returns 4 (go ahead and try it in irb).
How Do You Get The Remainder?
Funny enough, in Ruby you need to use the .remainder
function on a numeric type to get a consistent result. So:
num = -21
result = num.remainder(5)
and result will equal -1 as expected.
TL:DR
In Ruby if you want the remainder of a number, use the .remainder
method instead of the %
operator, especially if you are going to hit negative numbers.