Using math when conditional statements are unavailable

How’s this for a coding conundrum?

The Backstory

I like playing tabletop pen and paper roleplaying games. There’s a great site called roll20.net that allows you and your friends to play on a virtual tabletop online through your browser. It’s really neat, and intuititive, yada yada yada. One of the new features is the addition of player-made character sheets. They’re html files that have fields and buttons in them so you can fill out your character sheet, as well as use these handy buttons to do the dice rolls you need.

For example, if I wanted to do a hit check, I’d have to type this manually in the chat:

"/roll d20+@{strength_bonus}+[special hit feat]4+[racial bonus]2"

Or, I could just click a button in my character sheet that’ll do that roll for me. Much nicer, right? These buttons allow me to use variables and do some math on each roll in order make them work…

I was updating the Microlite20 character sheet. The human race in m20 adds +1 to all skill rolls. The fighter class adds +1 to all attack and damage rolls… and they get an additional +1 starting at level 5, and every 5 levels onward. So, levels 1-4 get a +1, 5-9 get +2, 10-14 get +3, and so on. I can factor those bonuses into the rolls. All I need are some if-statements on the rolls to determine whether or not the user has selected human and/or fighter, right?

The Problem

These sheets don’t allow conditional statements (if-then-else).

… crap. So how do I get around this?

They do allow one function: floor(). This function will take any decimal or fraction, and round it down to the nearest whole number. So if I gave it floor(8/5), that evaluates to floor(1.6), which the function then rounds down to: 1.

When selecting a class or race, you can apply a number value to that race and class.

… If you think you can solve this with the information given, go right ahead. If not, read on :)

The Solution

For the skill rolls, I only needed to add +1 to the end of every roll button, if they selected human. So, /roll d20+skill modifier+race bonus. All I had to do was add that race bonus on the end… how could I get the race bonus to work for human and only human? With that wonderful floor function. These are the values I set with the races:

  • Human-4
  • Elf-3
  • Dwarf-2
  • Halfling-1

If I did a floor(race/4), the only time it would evaluate to 1 is if you selected human :D! So now the skill rolls look like this:

/roll d20+skill modifier+floor(race/4)

If human, it’ll add 1 to the end, but if not, it’ll add 0, and mathematically, adding 0 to anything doesn’t change the value!

Ah, but what about those fighter additions? Those are even more difficult, because not only is there a +1, but you have to add more +1’s every 5 levels… what to do, what to do…

Floor function to the rescue again!

First, I determine the actual bonus itself before I determine whether or not the fighter class has been selected. floor(level/5) will give me a 1 if the level is between 5-9, and 2 if between 10-14, 3 if between 15-19… so I have that functionality ready to go, right? Well, there’s one little hiccup here: you still get a +1 if you’re between level 1-4… hmmmm…

The answer: simply add 1 to the floor function.

1+floor(level/5)

At levels 1-4, you’ll get a 1. Levels 5-9, you’ll get a 2, 10-14 gets a 3… and so on.

Great, so we got the +1 bonus per 5 levels logic down… now how do we get it to only happen when the user has selected fighter? Same way we determined whether the user had selected human: the floor function. I assign numeric values to their selection of what class they’ve chosen.

  • 4-Fighter
  • 3-Rogue
  • 2-Magi
  • 1-Cleric

So, floor(class/4) will only equal 1 if they’ve selected fighter.

Well, if it’s 0 on all the other classes, and I multiply that fighter bonus by 0, it evaluates to 0… but if I multiply it by 1, the bonus gets added!

So now the roll looks like this:

/roll d20+stat bonus+((floor(class/4))*(floor(level/5)+1))

Checking The Math

If they chose fighter, and they’re level 3…

((floor(class/4))*(floor(level/5)+1))
((floor(4/4))*(floor(3/5)+1))
((1)*(0+1))
1*1

There’s your added +1 bonus to the roll!

What if they chose fighter, and they’re level 18?

((floor(class/4))*(floor(level/5)+1))
((floor(4/4))*(floor(18/5)+1))
((1)*(3+1))
1*4

A bonus of +4!

What if they chose Rogue, and they’re level 6?

((floor(class/4))*(floor(level/5)+1))
((floor(3/4))*(floor(6/5)+1))
((0)*(1+1))
0*2

Bonus of 0. Shoulda selected a fighter!

Funny how one can get around if-logic simply by using mathematics, eh? :D