Author Topic: Exposing stat increase calculation to ruleset [patch inside]  (Read 10052 times)

Offline Roujin

  • Sergeant
  • **
  • Posts: 11
    • View Profile
Since Aldorn asked about this being a possibility / how difficult this would be in this post, I decided to investigate that for a bit.

Turns out that it wouldn't be all that hard from a coding standpoint.
However, it is a bit more challenging to come up with what values exactly to set in the ruleset, so that we can
a) match exactly the original / current calculation of stat gains.
and
b) give modders all the freedom they need wrt. changing the behavior.

This is what I have come up with for now (feedback appreciated):
Code: [Select]
    statGain:
      primary:
        bravery:
          requirement: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
          chance: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
          chanceDivisor: 11
          valueMin: 10
          valueMax: 10
        reactions:
          requirement: [1, 3, 6, 11]
          valueMin: [0, 1, 1, 2]
          valueMax: [1, 3, 4, 6]
        firing:
          requirement: [1, 3, 6, 11]
          valueMin: [0, 1, 1, 2]
          valueMax: [1, 3, 4, 6]
        throwing:
          requirement: [1, 3, 6, 11]
          valueMin: [0, 1, 1, 2]
          valueMax: [1, 3, 4, 6]
          enablesSecondary: false
        psiStrength:
          requirement: [1, 3, 6, 11]
          valueMin: [0, 1, 1, 2]
          valueMax: [1, 3, 4, 6]
        psiSkill:
          requirement: [1, 3, 6, 11]
          valueMin: [0, 1, 1, 2]
          valueMax: [1, 3, 4, 6]
        melee:
          requirement: [1, 3, 6, 11]
          valueMin: [0, 1, 1, 2]
          valueMax: [1, 3, 4, 6]
      secondary:
        tu:
          requirement: [1]
          valueMin: 0
          valueMax: 2
          remainderShareMin: 0
          remainderShareMax: 0.1
        stamina:
          requirement: [1]
          valueMin: 0
          valueMax: 2
          remainderShareMin: 0
          remainderShareMax: 0.1
        health:
          requirement: [1]
          valueMin: 0
          valueMax: 2
          remainderShareMin: 0
          remainderShareMax: 0.1
        strength:
          requirement: [1]
          valueMin: 0
          valueMax: 2
          remainderShareMin: 0
          remainderShareMax: 0.1

If I am not mistaken, this set of values should suffice to emulate the original xcom / current* behavior, while at the same time allowing modders all the freedom with regards to how exactly experience gain translates to stat gain. Note that it is not possible to change WHAT actions cause the experience gain in for one category; that would be a different topic altogether. Only the translation from experience (= successful actions taken) to stat gain is.

* there actually is a slight deviation in current trunk code to what ufopaedia has to say about original xcom calculation.
Code says:
Code: [Select]
return (int)(tier/2.0 + RNG::generate(0.0, tier));
... where tier can be either of 1.0, 2.0, 3.0, or 4.0. Zhis will result in the following chances:
edit - I missed some facts.. turns out the code is off even more than I thought.
Keep in mind that double->int conversion is rounding DOWN, not rounding to nearest int.

tier 1: random between 0.5 and 1.5 -> 50% for each of 0, 1
tier 2: random between 1.0 and 3.0 -> 50% for each of 1, 2
tier 3: random between 1.5 and 4.5 -> 1/6 for 1, 2/6 for 2, 2/6 for 3, 1/6 for 4
tier 4: random between 2.0 and 6.0 -> 25% for each of 2,3,4,5
(note that rounding is done after the random number generation, not to both the min and max value)

I don't know if this is deliberate or an oversight while coding.
It strikes me now that this may also be case in original xcom, just not explained so well in the wiki.
In this case I may revise the ruleset variables for primary stats a bit more...

edit: I once more thought about the code above and think now that it's most definitely a bug.
For example for tier 2 (3-5 successful actions), a random number is generated between 1.0 and 3.0. It is then converted to int (=rounded DOWN), which results in 1 in 50% of the cases and 2 in the other 50%. To be precise there is (maybe) a tiiiiiny tiny chance that the RNG hits exactly 3.0, but that's near impossible. So this code definitely needs a fix.
« Last Edit: June 29, 2014, 06:45:46 am by Roujin »

Offline Aldorn

  • Commander
  • *****
  • Posts: 750
    • View Profile
Re: Exposing stat increase calculation to ruleset
« Reply #1 on: June 28, 2014, 08:11:19 pm »
I'll follow your thread

Offline Roujin

  • Sergeant
  • **
  • Posts: 11
    • View Profile
Re: Exposing stat increase calculation to ruleset
« Reply #2 on: June 28, 2014, 11:27:06 pm »
I've revised the values a bit, mainly regarding bravery. I got rid of the "ChanceDivisor", in favor of just having a float-type chance in there. True, elevenths cannot be exactly specified as decimal numbers, but I think it is close enough. When I give the chances as
Code: [Select]
          chance: [0.0909, 0.1818, 0.2727, 0.3636, 0.4545, 0.5454, 0.6363, 0.7272, 0.8181, 0.9090, 1]
... the deviation from "true" 1/11th, 2/11ths etc. are just in the range of 0.000001 to 0.00001. I would say that this is acceptable. If not, just write some more 090909s into the rule file ;)

I also changed the value arrays for the primary stats to a "tierFactorMin" and "tierFactorMax", to more closely mimic the current computation.
But it still stands that the computation we have does NOT correspond to original xcom (according to ufopaedia).
I hope some dev reads this topic and can give some clarification on this (should it be fixed, or is it on purpose?).


So currently the rule variables look like this:
Code: [Select]
soldiers:
  - type: XCOM
     (... existing variables ...)
     statGain:
      primary:
        (bravery/reactions/firing/throwing/psiStrength/psiSkill/melee):
          requirement: (list of integers)
          chance: (number or list of numbers, default 1)
          valueMin: (number or list of numbers, default 0)
          valueMax: (number or list of numbers, default 0)
          tierFactorMin: (number or list of numbers, default 0)
          tierFactorMax: (number or list of numbers, default 0)
          remainderFactorMin: (number or list of numbers, default 0)
          remainderFactorMax: (number or list of numbers, default 0)
          enablesSecondary: (boolean, default true)
      secondary:
        (tu/stamina/health/strength):
          (same as above, except enablesSecondary)

Then the stat gain computation would be done like this (pseudocode):
Code: [Select]
tier = (highest index in requirement, so that requirement[index] <= experience)
if (RNG(0.0, 1,0) > chance[tier]) gain = 0;
else
  remainder = statcap - statcurrent;
  gain = RNG((int) (valueMin[tier] + tierFactorMin[tier] * (tier+1) + remainderFactorMin[tier] * remainder),
             (int) (valueMax[tier] + tierFactorMax[tier] * (tier+1) + remainderFactorMax[tier] * remainder));
endif

That way, the computations of bravery, all other primary stats, and the secondary stats are unified.
Only the default ruleset will specify what is currently hardcoded - namely that that chance is only used for bravery (it is always 1 for all other stats), or that the secondary skills (and only them) are calculated with regards to the remaining points to be gained until the stat cap; or that you always have the same secondary skill gain, regardless of how much primary-skill-experience you gained... modders will have free reign to change all that :)

now it only remains to be actually implemented  :P


PS: default ruleset will look like this:
Code: [Select]
    statGain:
      primary:
        bravery:
          requirement: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
          chance: [0.0909, 0.1818, 0.2727, 0.3636, 0.4545, 0.5454, 0.6363, 0.7272, 0.8181, 0.9090, 1]
          valueMin: 10
          valueMax: 10
        reactions:
          requirement: [1, 3, 6, 11]
          tierFactorMin: 0.5
          tierFactorMax: 1.5
        firing:
          requirement: [1, 3, 6, 11]
          tierFactorMin: 0.5
          tierFactorMax: 1.5
        throwing:
          requirement: [1, 3, 6, 11]
          tierFactorMin: 0.5
          tierFactorMax: 1.5
          enablesSecondary: false
        psiStrength:
          requirement: [1, 3, 6, 11]
          tierFactorMin: 0.5
          tierFactorMax: 1.5
        psiSkill:
          requirement: [1, 3, 6, 11]
          tierFactorMin: 0.5
          tierFactorMax: 1.5
        melee:
          requirement: [1, 3, 6, 11]
          tierFactorMin: 0.5
          tierFactorMax: 1.5
      secondary:
        tu:
          requirement: [1]
          valueMax: 2
          remainderFactorMax: 0.1
        stamina:
          requirement: [1]
          valueMax: 2
          remainderFactorMax: 0.1
        health:
          requirement: [1]
          valueMax: 2
          remainderFactorMax: 0.1
        strength:
          requirement: [1]
          valueMax: 2
          remainderFactorMax: 0.1
« Last Edit: June 28, 2014, 11:34:10 pm by Roujin »

Offline Roujin

  • Sergeant
  • **
  • Posts: 11
    • View Profile
Re: Exposing stat increase calculation to ruleset
« Reply #3 on: June 29, 2014, 06:28:09 am »
Well, I implemented it. Here's a patch.
However I talked to the devs on the IRC and they don't seem to be all that hyped on exposing all this to rulesets. :P So don't count on it actually getting into trunk.

Anyway, here's the patch.

Offline Roujin

  • Sergeant
  • **
  • Posts: 11
    • View Profile
Re: Exposing stat increase calculation to ruleset
« Reply #4 on: June 29, 2014, 06:45:18 am »
Here's some more documentation about how it works:

Each stat can have the following variables:
Code: [Select]
requirement: list of the exp requirement for each "tier".
chance: list of chances for each tier to get a stat increase at all
valueMin: list of minimum stat change
valueMax: list of maximum stat change
tierFactorMin: list of minimum stat change factor multiplied by tier
tierFactorMax: list of maximum stat change factor multiplied by tier
remainderFactorMin: list of minimum stat change factor multiplied by how much can still be gained in that stat
remainderFactorMin: list of maximum stat change factor multiplied by how much can still be gained in that stat
enablesSecondary: true or false - whether this stat counts into secondary stats

For secondary stats (health, tu, stamina, strength), enablesSecondary is obviously not useful, but otherwise, all these values are available for all of the stats.
All these values have sensible default values (mostly 0), and you can also just write a single number instead of a list of numbers, if you want every entry to be the same - except for requirement, that one has to be a list.



Here's an example:
Code: [Select]
    statGain:
      primary:
        firing:
          requirement: [1, 2, 4, 8]
          chance: [0.5, 0.75, 1, 1]
          valueMin: 0
          valueMax: [2, 2, 3, 4]
          tierFactorMin: 0.5
          tierFactorMax: 1
          enablesSecondary: false
(actually valueMin could be left out here because it defaults to 0)

This changes the firing accuracy skill to the following:
If a soldier scored 1 hit, he has a 50% chance of gaining points at all.
If he does, he gets between 0 (0 + 0.5*1 rounded down) and 3 (2 + 1*1 rounded down) points.
--
If he scored 2 to 3 hits, he has a 75% chance of gaining points at all.
If he does, he gets between 1 (0 + 0.5*2 rounded down) and 4 (2 + 1*2 rounded down) points.
--
If he scored 4 to 7 hits, he has a 100% chance...
to get between 1 (0 + 0.5*3 rounded down) and 6 (3 + 1*3 rounded down) points.
--
If he scored 8+ hits, he has a 100% chance...
to get between 2 (0 + 0.5*4 rounded down) and 8 (4 + 1*4 rounded down) points.
--
Finally, the line "enablesSecondary: false" means that exp gained for hitting targets will not trigger secondary stats (tu, health, stamina, strength) to increase, in contrast to original xcom behavior.


I hope this helps anyone who is willing to try my patch out ;)

Offline Aldorn

  • Commander
  • *****
  • Posts: 750
    • View Profile
Re: Exposing stat increase calculation to ruleset [patch inside]
« Reply #5 on: June 29, 2014, 12:47:23 pm »
It's very interesting, thanks
And a little more complex than just one or two threshold and a dozen parameters

It's a pity because the stat improvement mechanism is an important part of the game and we don't have any control on it
 :'(

Offline Falko

  • Commander
  • *****
  • Posts: 802
    • View Profile
Re: Exposing stat increase calculation to ruleset
« Reply #6 on: June 29, 2014, 12:54:55 pm »
It's a pity because the stat improvement mechanism is an important part of the game and we don't have any control on it
 :'(
i have to admit i never missed it
However I talked to the devs on the IRC and they don't seem to be all that hyped on exposing all this to rulesets. :P So don't count on it actually getting into trunk.
what about the "showing what soldier increased in stats"-window

Offline Roujin

  • Sergeant
  • **
  • Posts: 11
    • View Profile
Re: Exposing stat increase calculation to ruleset [patch inside]
« Reply #7 on: June 30, 2014, 01:35:54 am »
what about the "showing what soldier increased in stats"-window
SupSuper said that it's interesting (or something along the lines) and that he'd look at it when he finds the time. Warboy seems to be a critic of changes that depart from original xcom, so maybe making the screen optional and off-by-default might be a requirement before he agrees.

Even if it's not put into trunk, you can still use this you know, you'll just have to checkout, apply the patch, and compile the game yourself. ;)

Offline Aldorn

  • Commander
  • *****
  • Posts: 750
    • View Profile
Re: Exposing stat increase calculation to ruleset
« Reply #8 on: June 30, 2014, 11:51:18 am »
i have to admit i never missed it
IMO
1st : Be able to slow the stats progression will make it more valuable  :)
2nd : as I am involved on a mod where soldiers would be less killed (even if heavier injured), I'd like to have some control on this stat progression
But I agree this has not to be to implemented as soon as it would require lots of efforts

Offline Warboy1982

  • Administrator
  • Commander
  • *****
  • Posts: 2333
  • Developer
    • View Profile
Re: Exposing stat increase calculation to ruleset [patch inside]
« Reply #9 on: June 30, 2014, 12:46:33 pm »
i'm not against changes that depart from the original per-se, in fact some things can make quite nice additions, i just don't think we need every number in the code exported to the ruleset simply because it might be nice for modders. someone needs to draw a line somewhere.
there's already a TONNE of flexibility available through rulesets, and if anyone desires to change the internal mechanics - we're open source, it couldn't be easier.

Offline Aldorn

  • Commander
  • *****
  • Posts: 750
    • View Profile
Re: Exposing stat increase calculation to ruleset [patch inside]
« Reply #10 on: June 30, 2014, 02:12:51 pm »
i'm not against changes that depart from the original per-se, in fact some things can make quite nice additions, i just don't think we need every number in the code exported to the ruleset simply because it might be nice for modders. someone needs to draw a line somewhere.
there's already a TONNE of flexibility available through rulesets, and if anyone desires to change the internal mechanics - we're open source, it couldn't be easier.
Don't worry, I agree with you
I absolutely never forget the amazing job you did here, it's just wonderful and I'm very thankfully for this  ::)
My poor english make me offense you sometimes, my bad... :-\
When I ask for something, just answering no is ok for me, even if I am curious about arguments, but I will never complain about a negative answer, as all these requests would not be even imaginable if you did not provide such a nice wok ! ;)
« Last Edit: June 30, 2014, 02:17:41 pm by Aldorn »

Offline Warboy1982

  • Administrator
  • Commander
  • *****
  • Posts: 2333
  • Developer
    • View Profile
Re: Exposing stat increase calculation to ruleset [patch inside]
« Reply #11 on: June 30, 2014, 02:56:14 pm »
i'm just trying to clarify my stance, lest people call me a hypocrite.

i don't take offense at all - quite the opposite, in fact. i'm more than happy to discuss these sorts of things, and i'm sorry if i'm coming off as being blunt or rude at times.

and your English isn't poor; i've never had any trouble understanding you at least. i'd say better than average ;)

Offline Aldorn

  • Commander
  • *****
  • Posts: 750
    • View Profile
Re: Exposing stat increase calculation to ruleset [patch inside]
« Reply #12 on: June 30, 2014, 03:18:02 pm »
i'm just trying to clarify my stance, lest people call me a hypocrite.

i don't take offense at all - quite the opposite, in fact. i'm more than happy to discuss these sorts of things, and i'm sorry if i'm coming off as being blunt or rude at times.

and your English isn't poor; i've never had any trouble understanding you at least. i'd say better than average ;)
Let's say you are like SupSuper, efficient in your answers  ;)

Offline 0xEBJC

  • Colonel
  • ****
  • Posts: 145
  • Y'all are awesome! Thankful for this community.
    • View Profile
    • My Projects
Re: Exposing stat increase calculation to ruleset [patch inside]
« Reply #13 on: August 23, 2014, 08:38:01 pm »
I'm looking at making a new armour and I want to make have soldier stats improvement based on the number of missions the solder has been in, for example:

armors:

    stats:
       tu: (STR_SOLDIER_MISSIONS)/2
       firing: 5+STR_SOLDIER_MISSIONS

Looking for answers on two things. first, for the stat increases on items can it support an algebraic function vice a fix number and secondly I have no idea what the variable I would call to assign the # of missions in the calculation,  I'm starting to look over the source code, but I haven't found the answer yet.

Thanks