Ruby Mod Operator Does Not Behave As Expected

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.

I Want to Be a Better Developer