PDA

View Full Version : Limiting a calculation based on another?



Wil
March 13th, 2007, 07:30
I'm slowly working on a Tribe 8 character sheet, but I think I've hit a snag.

Spiritual Stamina is 25+(5*(Psyche + Willpower)), minimum 1 and maximum Stamina+15. For example, the average Stamina is 25 so that means Spiritual Stamina is capped at 40.

I've got the calculation down along with the minimum, however Stamina is a derived trait very similar to Spiritual Stamina. I can't quite figure out how to limit it. I don't think a straight <valuemap> will work neither will <limits>. Does anyone have any idea how to handle this?

As an aside, I don't know how v2 will handle this sort of thing but the capability of using XSLT syntax would help tremendously (along with a strongly typed XSD).

Dachannien
March 13th, 2007, 19:49
Yep, you can do this. It's kind of a PITA though ;)

Let's call the variable name for stamina "sta" and the variable name for spiritual stamina as you've calculated it "ssta1". The final value for ssta will just be in "ssta".

We'll need a helper variable first. Anytime you need to do some mathematical operation using a constant, you use this value and put it through a valuemap to get the constant you need. The value of this variable is, by itself, zero.


<numbercontrol name="sstahelper">
<invisible />
</numbercontrol>

Next, you need to calculate what the maximum value that ssta will be limited to. Note the use of the sstahelper value, piped through a valuemap, to get 15.


<numbercontrol name="maxssta">
<invisible />
<source name="sta" />
<source name="sstahelper" valuemap="0:15" op="+" />
</numbercontrol>

Then you calculate the difference between the maximum value and the calculated value of ssta1.


<numbercontrol name="maxssta1">
<invisible />
<source name="maxssta" />
<source name="ssta1" op="-" />
</numbercontrol>

The reason for this isn't clear yet, I know, but it'll work, trust me ;)

Then you calculate the same value, but add 1 to it (using sstahelper) this time:


<numbercontrol name="maxssta2">
<invisible />
<source name="maxssta" />
<source name="ssta1" op="-" />
<source name="sstahelper" valuemap="0:1" op="+" />
</numbercontrol>

Next, you divide the first result by the second result. That is, you calculate

(maxssta - ssta1) / (maxssta - ssta1 + 1)


<numbercontrol name="maxssta3">
<invisible />
<source name="maxssta1" />
<source name="maxssta2" op="/" valuemap="0:-1" />
</numbercontrol>

When we divide two numbers, we have to make sure that the denominator never equals zero, or bad things can happen. In this case, I'm pretty sure it's just the wrong result. Nevertheless, we specify a valuemap to make 0 count as -1 for this division.

The reason is as follows.

We need a way to differentiate between situations where we want to take the maximum ssta (i.e., stamina + 15) or the calculated ssta (that formula you posted). You choose based on which one is less. But FG1 doesn't have conditional statements of any sort, so we have to use a math trick. In the formula

(maxssta - ssta1) / (maxssta - ssta1 + 1)

an interesting thing happens. Suppose maxssta is greater than ssta1. Then (maxssta - ssta1) will be positive, and therefore, (maxssta - ssta1 + 1) will be positive *and* greater than (maxssta - ssta1). When you divide the two, you always get a value just less than 1, which FG rounds down to zero.

Now suppose maxssta is less than ssta1. (maxssta - ssta1) will be negative, and at most, (maxssta - ssta1 + 1) will be zero since everything here is an integer. But we've said that we're treating a 0 as a -1 in this case, so we're dividing a negative number by another negative number. The result will be non-negative, and since the absolute value of (maxssta - ssta1) is greater than or equal to (maxssta - ssta + 1), the result will actually be positive.

So, from that formula, we get a 0 if maxssta is bigger, and we get 1 or more if maxssta is smaller. Now that we can work with!


<numbercontrol name="maxssta4">
<invisible />
<source name="maxssta" />
<source name="maxssta3" op="*" valuemap="0:0,1:1,2:1" />
</numbercontrol>

Remember, we want to pick whichever value is smaller. If maxssta3 was 1 or more, then maxssta was smaller, so we want to pick it. If maxssta3 was 0, then we don't want to pick it. So we multiply maxssta by 1 if we want to pick it and by 0 if we don't. Then we do the opposite for ssta1:


<numbercontrol name="maxssta5">
<invisible />
<source name="ssta1" />
<source name="maxssta3" op="*" valuemap="0:1,1:0,2:0" />
</numbercontrol>

Now, whichever value was larger has been multiplied by zero. Exactly one of the values will be zero, and the other will be the value we want, but we don't know which one is which. So, we add them:


<numbercontrol name="ssta">
<source name="maxssta4" />
<source name="maxssta5" op="+" />
</numbercontrol>

And that's the answer. This value you can display directly (remember to add a bounds tag and maybe a <value type="readonly" /> tag if so) or make invisible with an <invisible /> tag.

By the way, if the original calculated value can go negative, you may be able to pipe that value through a valuemap, only specifying negative numbers and zero (like 0:1,-1:1,-2:1,....). Numbers not specified in a valuemap are mapped to themselves. But if there are too many possible negative values to specify in a valuemap, you can just use the above procedure again. You would end up using it twice - once like this, and then take that answer and do the procedure with the subtractions in the reverse order and the last two valuemaps switched.

Hope this helps! :)

Wil
March 14th, 2007, 02:27
Thanks! I haven't read through it in detail, but I knew that it was going to involve shuffling numbers around. I'll let you know how it works out. Being able to finish the Tribe 8 character sheet will enable me to finish them for Jovian Chronicles, Heavy Gear and SilCore - having them available may entice DP9 players to use FG (I know I'm doing this with an eye towards an online game). I haven't heard back yet from the business manager at DP9 but I may get permission to build a full or partial rulesset for SilCore as well.

EDIT: Actually, it worked like a charm. Should probably go down in the annals of Rube Goldberg math ;)

DrDeth
March 18th, 2007, 16:47
This is an excellent answer and no doubt something that may come up a lot with new/custom rulesets.

Perhaps the admins could sticky this or add it to a FAQ somewhere.

sloejack
March 18th, 2007, 19:41
This is an excellent answer and no doubt something that may come up a lot with new/custom rulesets.

Perhaps the admins could sticky this or add it to a FAQ somewhere.

I agree that this is a great response. However, calculations and rulesets are handled much differently in 2.0, I'm not sure this would be a good idea since it could lead to confusion.

Dachannien
March 18th, 2007, 21:03
Yeah, I've heard that they're using some sort of scripting language in v2.0, which means you don't have to read the Necronomicon to figure out how to make it work.

Believe me, I wouldn't have sacrificed 1d100 sanity points including that Rube Goldberg math in my own custom ruleset if I didn't have to ;)

DrDeth
March 23rd, 2007, 09:51
Where can I get information about v2 ? It'll be a great help for our RuleSet editor to be able to work when v2 comes out. :bandit:

sloejack
March 23rd, 2007, 12:50
You can find v2 Reference Documentation here (https://www.fantasygrounds.com/refdocbeta/). You may want to reach out to the devs and see about getting access to the beta. Probably the most significant change from your tools perspective is that rulesets are now primarily about mechanics and character sheets. Rulebook data is contained in modules seperate from the rulesets. There are some structural differences in the xml as well but nothing you shouldn't be able to overcome.