Implicit type conversion in GDScript - When math gets in the way

2min read
Game Dev Godot Engine

November 8, 2018

Formula thumbnail

While coding a simple AI for my (italian) Godot video tutorial series, I needed vectors with these kind of random values:

  • Vector2(0, 1)
  • Vector2(-1, 1)

Essentially I wanted to generate random values of 1, 0 or -1 and then use them as Vector2 coordinates.

There are multiple (simple) ways of doing this, but the first that came to my mind was a slightly convoluted mathematical approach:

I'm lazy and I prefer using pen and paper instead of MathJax, yes.

that translated into GDScript code is somethink like:

pow(-1, randi() % 2) * randi() % 2

Even if mathematically correct, this expression does not work as expected. When executing it, Godot complains about a bad float argument for the modulo operator %.

Error screen

The problem is that pow() returns a float number and I was not taking this into account (more on this later);

Types highlighted

this means that pow(-1, randi() % 2) * randi() is a multiplication of a float and an integer.
In this case GDScript will implicitly convert the integer to float and thus the result of the multiplication will be a float value, and here it is the problem: this float value will be used as operand for the modulo operator and this is not a valid operation.

I did not see this error at first because I was thinking in mathematical terms and (-1)^n, for n positive natural number, is always an integer number.

Fixing the expression

# fixed
pow(-1, randi() % 2) * (randi() % 2)

# old 
pow(-1, randi() % 2) * randi() % 2

Just use the parenthesis to give precedence to the ending randi() % 2 and the problem is solved.

It’s not a super interesting read, but I think that it’s always good to remember that the math that we use in code development is really different from the math that we use in other contexts.