Permutation math code?

One part of my application has 6 different inputs, where each input has 5 different possible values. This amounts to 15,625 permutations. I would like to believe that I don't need to code each of them, but I'm really not sure. I started coding it as if I had to code each one, but it seemed to me like there must be a better way. So I came here to see if any more experienced coders know a better way to do this.

Is there another way? Except for having to code every permutation?

Equation Explanation: There are 6 limbs (inputs). Each entry depends on its percentage of health remaining. These dependencies (expressed as a percentage) are less than or equal to 0, greater than 0 and less than or equal to 25, greater than 25 and less than or equal to 50, greater than 50 and less than or equal to 75, and greater than 75. Each permutation will most often lead to a different result. This output is displayed in the application for use by the user.

[EDIT] This is not a damage calculation. These are penalties applied to players' stats based on how much damage they have taken. The expected results either do not affect their stats or decrease their stats. Sometimes the number subtracted is the same for different variables. If you look at the code below, you can see that the number is the same for head > 0.0 && head <= 0.25

and chest > 0.0 && chest <= 0.25

and also chest > 0.25 && chest <= 0.50

and leftarm > 0.25 && leftarm <= 0.50

andrgitharm > 0.25 && rightarm <= 0.50

[EDITS] I'll answer the comments here:

@Frank N. Stein: Oops. Thanks for the correction:)

@aioobe: I edited equation explanation

to hopefully clarify the expected results.

@ian: These values ​​cannot be worked out as they are percentages. I can never work them out.

@ Marco13: It seems like it's just because I haven't finished coding each permutation yet. On the other hand, I don't think I need to display the dead. I can just leave these permutations from the computation as that will take care of the other activity.

@aioobe: This is better than listing the results suggested by @Ian and @Durandal.

@Danil Gaponov: Is this better or worse than what @Durandal suggested in his / her answer?

@Durandal: I've updated equation explanation

, hopefully it will be clearer what I expect for each of these results.

Thank you for your patience:)

Can I do something similar to this:

//  HEALTH
//  N > 0.75            == Full
//  N > 0.50 && <= 0.75 == HighHealth
//  N > 0.25 && <= 0.50 == MedHealth
//  N > 0.00 && <= 0.25 == LowHealth
//  N <= 0.00           == Dead

      

IE I could write h == Full

or h == Health.Full

. It would make my life a lot easier so that the code is much easier to read. Although I still have to work out each permutation, it will be a little more manageable.

Another idea I have is to put this computation in another class and run it within an activity. Something like that:

//      SETTING DATA
//      WEAPON 1
//      MELEE
weapon1attack.setText(PenaltiesMeleeHelper);
weapon1accuracy.setText(PenaltiesMeleeHelper);
//      RANGED
weapon1thrownattack.setText(PenaltiesThrownHelper);
weapon1thrownaccuracy.setText(PenaltiesThrownHelper);
//      WEAPON 2
//      MELEE
weapon2attack.setText(PenaltiesMeleeHelper);
weapon2accuracy.setText(PenaltiesMeleeHelper);
//      RANGED
weapon2thrownattack.setText(PenaltiesThrownHelper);
weapon2thrownaccuracy.setText(PenaltiesThrownHelper);

      

Is it possible?

[EDIT] Will the math algorithm work? Let's say I have a Checker that checks for penalties every time an action starts. If he finds a fine / penalties, then he will add them all together for me and subtract from the corresponding statistics.

For example:

// There are 3 main outcomes that are suffered for being damaged too much
// The reduction of parry (PRY), dodge (DOD), and damage & accuracy (AM)
// The deductions range from -2 to -5. 
// I could declare Enums for each type

PRY2 = (- 2)
DOD2 = (- 2)
AM2 = (- 2)

PRY2 would be put into the equation if la > 0.50 && la <= 0.75 || ra > 0.50 && ra <= 0.75
DOD2 would be put into the equation if la > 0.50 && la <= 0.75 || ra > 0.50 && ra <= 0.75 || ll > 0.50 && ll <= 0.75 || rl > 0.50 && rl <= 0.75
AM2 would be put into the equation if la > 0.50 && la <= 0.75 || ra > 0.50 && ra <= 0.75 || c > 0.50 && c <= 0.75

PRY3 = (- 3)
DOD3 = (- 3)
AM3 = (- 3)

PRY3 would be put into the equation if c > 0.25 && c <= 0.50 || la > 0.25 && la <= 0.50 || ra > 0.25 && ra <= 0.50 || 
DOD3 would be put into the equation if c > 0.25 && c <= 0.50 || la > 0.25 && la <= 0.50 || ra > 0.25 && ra <= 0.50 || ll > 0.25 && ll <= 0.50 || rl > 0.25 && rl <= 0.50 
AM3 would be put into the equation if c > 0.25 && c <= 0.50 || la > 0.25 && la <= 0.50 || ra > 0.25 && ra <= 0.50 || 

PRY4 = (- 4)
DOD4 = (- 4)
AM4 = (- 4)

PRY4 would be put into the equation if la > 0.0 && la <= 0.25 || ra > 0.0 && ra <= 0.25 || ll > 0.0 && ll <= 0.25 || rl > 0.0 && rl <= 0.25
DOD4 would be put into the equation if la > 0.0 && la <= 0.25 || ra > 0.0 && ra <= 0.25 || ll > 0.0 && ll <= 0.25 || rl > 0.0 && rl <= 0.25
AM4 would be put into the equation if la > 0.0 && la <= 0.25 || ra > 0.0 && ra <= 0.25 || ll > 0.0 && ll <= 0.25 || rl > 0.0 && rl <= 0.25

PRY5 = (- 5)
DOD5 = (- 5)
AM5 = (- 5)

PRY5 would be put into the equation if h > 0.0 && h <= 0.25 || c > 0.0 && c <= 0.25 || la <= 0.0 || ra <= 0.0 || ll <= 0.0 || rl <= 0.0
DOD5 would be put into the equation if h > 0.0 && h <= 0.25 || c > 0.0 && c <= 0.25 || la <= 0.0 || ra <= 0.0 || ll <= 0.0 || rl <= 0.0
AM5 would be put into the equation if h > 0.0 && h <= 0.25 || c > 0.0 && c <= 0.25 || la <= 0.0 || ra <= 0.0 || ll <= 0.0 || rl <= 0.0

// I'm not sure how, but somehow it would know, since it PRY, then it knows to take the Enum and deduct it from the PRY slot and not the DOD or AM slots. 
// Is this a step in the right direction? 

      

Here's the code I have (encoding each permutation):

//      SETTING DATA
//      WEAPON 1
//      MELEE           
        try {
            float STRF = NumberUtils.toFloat(pref.getString("strength", ""), 0.0f);
            float MCF = NumberUtils.toFloat(pref.getString("melee", ""), 0.0f);
            float W1AttF = NumberUtils.toFloat(pref.getString("w1attack", ""), 0.0f);

    // ALL LIMBS > 0.00 && h <= 0.25
            if (MCF != 0.0 && W1AttF != 0.0 && h > 0.0 && h <= 0.25 && c > 0.0 && c <= 0.25
                    && la > 0.0 && la <= 0.25 && ra > 0.0 && ra <= 0.25 && ll > 0.0 && ll <= 0.25
                    && rl > 0.0 && rl <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 26));
            } 
        // HEAD h > 0.25 && h <= 0.50   
            else if (MCF != 0.0 && W1AttF != 0.0 && h > 0.25 && h <= 0.50 && c > 0.0 && c <= 0.25
                    && la > 0.0 && la <= 0.25 && ra > 0.0 && ra <= 0.25 && ll > 0.0 && ll <= 0.25
                    && rl > 0.0 && rl <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 21));
            }
            // HEAD h > 0.50 && h <= 0.75   
            else if (MCF != 0.0 && W1AttF != 0.0 && h > 0.50 && h <= 0.75 && c > 0.0 && c <= 0.25
                    && la > 0.0 && la <= 0.25 && ra > 0.0 && ra <= 0.25 && ll > 0.0 && ll <= 0.25
                    && rl > 0.0 && rl <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 21));
            }
            // HEAD h > 0.75    
            else if (MCF != 0.0 && W1AttF != 0.0 && h > 0.75  && c > 0.0 && c <= 0.25
                    && la > 0.0 && la <= 0.25 && ra > 0.0 && ra <= 0.25 && ll > 0.0 && ll <= 0.25
                    && rl > 0.0 && rl <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 21));
            }
        // CHEST c > 0.25 && c <= 0.50
            else if (MCF != 0.0 && W1AttF != 0.0 && h > 0.0 && h <= 0.25 && c > 0.25 && c <= 0.50
                    && la > 0.0 && la <= 0.25 && ra > 0.0 && ra <= 0.25 && ll > 0.0 && ll <= 0.25
                    && rl > 0.0 && rl <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 26));
            } 
            // CHEST c > 0.50 && c <= 0.75
            else if (MCF != 0.0 && W1AttF != 0.0 && h > 0.0 && h <= 0.25 && c > 0.50 && c <= 0.75
                    && la > 0.0 && la <= 0.25 && ra > 0.0 && ra <= 0.25 && ll > 0.0 && ll <= 0.25
                    && rl > 0.0 && rl <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 26));
            } 
            // CHEST c > 0.75
            else if (MCF != 0.0 && W1AttF != 0.0 && h > 0.0 && h <= 0.25 && c > 0.75
                    && la > 0.0 && la <= 0.25 && ra > 0.0 && ra <= 0.25 && ll > 0.0 && ll <= 0.25
                    && rl > 0.0 && rl <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 26));
            } 
        // HEAD ONLY    
            else if (MCF != 0.0 && W1AttF != 0.0 && h > 0.0 && h <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 5));
            } else if (MCF != 0.0 && W1AttF != 0.0 && h <= 0.0) {
                weapon1attack.setText("Dead");
            } 
        // CHEST ONLY   
            else if (MCF != 0.0 && W1AttF != 0.0 && c > 0.0 && c <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 5));
            } else if (MCF != 0.0 && W1AttF != 0.0 && c > 0.25 && c <= 0.50) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 3)); 
            } else if (MCF != 0.0 && W1AttF != 0.0 && c > 0.50 && c <= 0.75) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 2));
            } else if (MCF != 0.0 && W1AttF != 0.0 && c <= 0.0) {
                weapon1attack.setText("Dead");
            } 
        // LEFT ARM ONLY    
            else if (MCF != 0.0 && W1AttF != 0.0 && la > 0.0 && la <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 4));
            } else if (MCF != 0.0 && W1AttF != 0.0 && la > 0.25 && la <= 0.50) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 3)); 
            } else if (MCF != 0.0 && W1AttF != 0.0 && la > 0.50 && la <= 0.75) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 2));
            } else if (MCF != 0.0 && W1AttF != 0.0 && la <= 0.0) {
                weapon1attack.setText("Dead");
            } 
        // RIGHT ARM ONLY   
            else if (MCF != 0.0 && W1AttF != 0.0 && ra > 0.0 && ra <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 4));
            } else if (MCF != 0.0 && W1AttF != 0.0 && ra > 0.25 && ra <= 0.50) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 3)); 
            } else if (MCF != 0.0 && W1AttF != 0.0 && ra > 0.50 && ra <= 0.75) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 2));
            } else if (MCF != 0.0 && W1AttF != 0.0 && ra <= 0.0) {
                weapon1attack.setText("Dead");
            }   
        // LEFT LEG ONLY    
            else if (MCF != 0.0 && W1AttF != 0.0 && ll > 0.0 && ll <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 4));
            } else if (MCF != 0.0 && W1AttF != 0.0 && ll <= 0.0) {
                weapon1attack.setText("Dead");
            }   
        // RIGHT LEG ONLY   
            else if (MCF != 0.0 && W1AttF != 0.0 && rl > 0.0 && rl <= 0.25) {
                weapon1attack.setText(Float.toString((STRF + MCF + W1AttF) - 4));
            } else if (MCF != 0.0 && W1AttF != 0.0 && rl <= 0.0) {
                weapon1attack.setText("Dead");
            }   

            else if (W1AttF == 0.0 || MCF == 0.0) {
                weapon1attack.setText("");
            } else if (MCF != 0.0 && W1AttF != 0.0) {
                weapon1attack.setText(Float.toString(STRF + MCF + W1AttF));
            }   
        }
        catch (NumberFormatException ignore) {}

      

+3


source to share


2 answers


Too little to continue with what the desired outcome looks like ongoing for each case. From the comments in the code, I am compiling my own kind of RPG damage calculation.

It is best to first describe the problem in natural language, or rather not the problem, but the rules that govern the outcome of each combination of parameters. By looking at patterns out of the rules, you can usually identify a fairly small set of cases that can be expressed as mathematical formulas.

If you really want to be absolutely free to control the results of each case, you will need to enumerate the cases and build a data structure containing the result for each possible case (for example, a data file that lists the results for each combination that is read in memory in some form or another) ...

Reflecting on what I see in your code, I am assuming that you are trying to figure out damage based on location, weapons, defenses, etc.



This is good for using simple mathematical formulas, for example. first define the location, and depending on that assign the dmanage modifier (pseudocode):

 modifier = 1.0; // defaults to "normal" damager
 switch (location) {
     case HEAD:
         modfier *= 2.00; // double damage
     case CHEST:
         modifier *= 0.75; // 75% damage
     default:
         // elsewhere: no change
         break;
 }
 // ... further modify based on other parameters like attack
 // type, defense type whatever you have

 // now figure out a base damage, purely fictional
 baseDmg = attack - defense;
 // we don't want negative damage in case def > att,
 // so if negative set to 1.0
 baseDmg = Math.max(baseDmg, 1.0);

 // caluclate final dmg using modifier
 realDmg = baseDmg * modifier;

 if (realDmg > life)
     // dead!
 else 
     // ouch!

      

Try to break your rules so you can write it like the example above.

+2


source


You can create a method that converts your parameters to a unique integer from 0 to 15625 (5 ^ 6) corresponding to your permutation, and then forks accordingly.



Edit: Another option might be to move these rules into a config file and process it in Java code.

0


source







All Articles