ID:38130
 
Keywords: math
Introducing the Yxcabax Formula

Consider the two scales below. Imagine that each letter is a mathematical point - it doesn't take up any space. So the first scale is six units long, and the second is nine units long.

a....b..c
x......y...z


Look at b and y on the scales. y is six units from x, while b is only four units from a. But in terms of proportion, they are the same:

* a is twice as far from b as b is from c
* x is twice as far from y as y is from z

As you dive into Building Your Own Net Dream, there's a fair chance that you'll encounter a situation where a value on one scale needs to be converted into a value on another scale. This is quite possible, and even easy; this article's goal is to show you how to do it. We'll get to several examples eventually, but first I want to tantalize you with some delicious mathematics. (If you don't like math, don't worry. This is basic stuff and it'll be over soon, and it will be worth your while, honest.)


Deriving the Yxcabax Formula (and its name)

I'll admit right up front that this formula is not my own invention. Or rather, I did invent it, but someone beat me to it -- actually, probably a few million people (give or take a couple orders of magnitude) have beaten me to it over the centuries. The Yxcabax Formula is what mathematicians call the Linear Interpolation Formula. You can see it at http://en.wikipedia.org/wiki/Linear_interpolation; their version is uglier, but it's basically the same thing. So why do I call it the Yxcabax Formula? Two reasons:

1) To my untutored ear, it sounds like a name the Mayans or Aztecs might have come up with. When I started this article several years ago, it was going to be an educational odyssey cleverly concealed in an Indiana Jones-style pulp adventure story. I finally decided to take a more direct approach, but I still like the name.

2) If you can remember the word Yxcabax, you can probably also remember the formula itself. (I'm serious. You'll see.)

Let me show you how to derive the formula just from what we can observe about the scales above. It's really pretty easy. The distance between a and c (which is c - a), and the distance between a and b (b - a), can be combined to form a ratio. We know that this ratio is the same as the ratio of (z - x) to (y - x). So we start here:

(c - a) / (b - a) = (z - x) / (y - x)

We want to solve for z, so how can we get it alone? First let's multiply by the denominator (y - x).

(y - x) * (c - a) / (b - a) = (z - x)

Now add x to the left side to isolate z.

(y - x) * (c - a) / (b - a) + x = z

If you look very carefully, you may just see why I call it the Yxcabax Formula.


DM Code for the Yxcabax Formula

Ahh, that was good math, wasn't it? Yes indeed. And guess what? We were also writing DM code the whole time! Don't believe me? Create a new Dream Maker environment and paste this into it.

proc/Yxcabax(a, b, c, x, y)
return (y - x) * (c - a) / (b - a) + x


mob/verb/yxcabax(a as num, b as num, c as num, d as num, e as num)
world << Yxcabax(a, b, c, d, e)


Of course, in your game you probably don't want to provide the verb to your players; that's just there to help you follow along with the examples below. Note that in the verb, I used d and e instead of x and y. I did that deliberately, to help you appreciate the versatility of procedure arguments. Enjoy.

There's one thing that could go wrong here. Can you spot it? It's the division by (b - a). If b and a are identical, BYOND will give you an ugly runtime error, and that failure could easily cascade throughout your game. So make sure you're always providing two distinct reference points for a and b. Since a and b are the points that define the scale you're mapping from, in many cases they'll be fixed values, but it bears keeping in mind.

Here's something to remember: in many of the forthcoming examples, we'll want an integer value (a plain number with no decimal or fractional part). BYOND's built-in round() proc can handle this. If your game only needs to use the formula for integer results, you could include the call to round() in the Yxcabax proc itself, but in a game where the formula is used for many different purposes, it might be wiser to create a "wrapper" proc called RoundedYxcabax()... or just call round() wherever you need it.

You can also rename Yxcabax() to Interpolate() if it makes you feel smarter.


Sample Applications for the Yxcabax Formula

Let's imagine we're working on an outer-space game, Galaxy under Glass. Players will be able to acquire spaceships and tool around the universe kicking up trouble. The examples below will follow this science-fiction theme, but of course the mathematics underlying the Yxcabax Formula will work in almost any setting. Remember, too, that this isn't an exhaustive list -- I've just tried to show some of the most obvious examples. Once you are familiar with the principles involved, you will undoubtedly come up with ideas of your own.


Conversions

For convenience, shipboard computers can be set to display planetary scan data in Imperial or metric measurements. Here we'll consider temperature conversion. We know that in the metric system, water freezes at 0 degrees and boils at 100 degrees, whereas in the Imperial system, water freezes at a much more picturesque 32 degrees and boils at 212 degrees. Let's say that in the code we assign each planet an average equatorial temperature in degrees Celsius, and that for the planet Farinia it's 25 degrees.

For the Yxcabax Formula, then, our values are

a= 0 (Celsius freezing point)
b = 100 (Celsius boiling point)
c = 25 (Farinia's temperature)
d = 32 (Fahrenheit freezing point)
e = 212 (Fahrenheit boiling point)

Try it out and you'll see that 25 degrees Celsius is a balmy 77 degrees Fahrenheit.

Many other measurement conversions are even easier to handle with the Yxcabax Formula, because unlike the temperature scales above, many measurement scales share a value in common -- namely, zero. 0 dollars is 0 denarii; 0 miles is 0 kilometers. In these cases, we only need know a single (non-zero) point of equivalence. Converting pounds to stone? A quick Web search will tell you that 1 pound = 0.0714285714 stone. Those will be our values for b and y. Since we can use 0 for the values of a and x, we're ready to go!


Stats to visual feedback

The player's ship has a maximum and current hull strength (a.k.a. hit points). The maximum strength can be increased throughout the game by adding more armor. We want to overlay a "health bar" on the ship as a rough appraisal of its current status. For simplicity, the bar has only eleven states, from empty (0), to full (10). Resulting values:

a = 0 (hull destroyed)
b = maximum hull strength
c = current hull strength
x = 0 (empty bar)
y = 10 (full bar)

Note that we'll need to use round() on the result to get an integer value for the health bar. Also, if we decide to create a separate indicator bar for armor, we'll want to be sure to handle the division-by-zero case of an unarmored ship (since the b value, maximum armor, equals the a value, minimum armor).


Visual feedback to stats

The player's ship has a "throttle" control that can slide from 0 to 100 percent power. Let's say we've made it so sensitive the player can actually slide the throttle to 101 different settings (0% power to 100%). When the player slides the throttle, we want to change the ship's speed. Values:

a = 0 (engines off)
b = 100 (full throttle)
c = current throttle setting
x = 0 (dead in the water)
y = ship's maximum speed


Rates to times

Think carefully before imitating this example; it's a good example, but since it involves predicting the future, just remember that rates of alteration are prone to change. For example, a ship with a slow oxygen leak may run into a battle with space pirates, and during the battle, the pirates may hit the ship and make the leak more severe. On the other hand, a self-sealing hull or a repair robot may stop all the leaking.

That said, we can at least give the player estimates with the best information that's available. So let's say ten seconds ago the player's oxygen was at 700 units, and now it's at 540 units. Every ten seconds we want to give the player an updated estimate of when his oxygen will run out, based on the last ten seconds of leakage.

Values to plug in to the formula:

a = 700 (oxygen on board ten seconds ago)
b = 540 (oxygen on board now)
c = 0 (future value of the ship's oxygen when it all runs out)
x = -10 (ten seconds ago)
y = 0 (no seconds ago)

At the current rate of leakage, the oxygen supply will reach 0 in 33.75 seconds. Note that this is another one of those cases where you have to watch for division by zero. If there's no leak, a and b will be the same (and there's no point in warning the player).


Large scale to small

Let's do a little plagiarizing. If you've played Mass Effect, you know that there are many "side missions" that allow you to drive a Moon Patrol buggy around a planet's surface and look for cool stuff. There's also a map that lets you see some of the locations where you can find goodies. In our game, we can plant an invisible marker at each such location on a planet's surface (i.e., the planet's full map level, maybe 99x99), and use our formula to decide where these locations should be displayed on the player's 11x11 map view. (How to handle the map view is an interesting choice. We could temporarily switch the player's client.eye to a mob on another map level, in a small space specifically reserved for showing the mini-map. But it might be slicker, not to mention simpler, to use screen objects to overlay the locations of interest, plus the buggy's current position, right on the gameplay screen without ever interrupting the action.)


If You Ignore the Yxcabax Formula It Will Bury You

This section should more properly be called "Conclusion," but that's no fun. I hope that the examples above have at least given you a taste of the many possibilities inherent in this simple little formula. And if you don't have a use for linear interpolation in your current project, I hope you will at least tuck it away in the back of your mind -- it may save you from having to "reinvent the wheel" one day.
Looks...interesting... But I have absolutely no clue what its supposed to be used for and that makes it kind of hard to get into the article.
Foomer wrote:
Looks...interesting... But I have absolutely no clue what its supposed to be used for and that makes it kind of hard to get into the article.

id assume it has to do with shapes, scaling and proportion calculations. Its very interesting but i cant use it for my game really.
But I have absolutely no clue what its supposed to be used for

Just skip to the "sample applications" section for several practical examples of how it can be used.
Well, I guess it just needs pictures then, because I still don't understand what its all about. :P
I wouldn't say its main use would be graphics, rather converting a number from one scale to another.

Like the example of converting temperatures from Celsius to Fahrenheit. It could also be used for converting from miles to meters, or anything between any two scales.

Remember cross-multiplying in Algebra? Its basically that.

Note: There seems to be a typo. In the first example the variables are a,b,c,d,e whereas they should be a,b,c,x,y