2

I know there is a simple answer to this - I just cant think of it. I'm developing a strategy game where scenery upgrades its levels based on points. So the result I'm looking for is this...

Level from points...

1 <= 1  
2 <= 2,3  
3 <= 4,5,6  
4 <= 7,8,9,10  
5 <= 11,12,13,14,15

you can see where this is going. So can anyone remind me of the simple formula to do this so I can go away and bow my head in shame?

armegalo
  • 23
  • 2

4 Answers4

2

The sequence you describe is a very known one, named triangular numbers sequence, that is defined by the formula:

maxpt = (lv * (lv + 1)) / 2

In your specific case, this formula gives the maximum of points maxpt you can have and still be at level lv.

But you want the inverse of that. You want to know wich level lv you will be for a given number of points pt. This is named the triangular root of the number (as an analogy to the square root).

You can directly invert the formula through the Bhaskara equation, but you'll need to do some tricks to correct the base index. That gives:

lv = (int)((Math.sqrt(8 * (pt - 1) + 1) - 1) / 2) + 1

That works for pt >= 1. For pt = 0 just return 0 to avoid a float point error (square root of a negative number).

You can surely find more elegant solutions to this over the internet, though.

Rodrigo Rodrigues
  • 7,545
  • 1
  • 24
  • 36
  • Yess, I was SURE it existed. There was me searching for number pyramids when I just needed triangular numbers lol! – armegalo Jun 26 '18 at 10:58
  • If the answer helped you to solve your problem, you can mark it as accepted and make it easier for other people with the same problem to find the solution. – Rodrigo Rodrigues Jun 27 '18 at 03:39
1

Hmm I could not find any algorythm doing this.

You can auto generate an array with this matching at the Awake() of your game:

public int startLevel = 1;
public int scoreLimit = 100;
private int currentLevel = 0;
public int[] matchingArray;

void Awake()
{
    matchingArray = new int[scoreLimit + 1];
    currentLevel = startLevel;
    int currentScore = 1;
    int availableScoreSteps = 1;

    while (currentScore <= scoreLimit)
    {
        while (availableScoreSteps > 0 && currentScore <= scoreLimit)
        {
            matchingArray[currentScore] = currentLevel;
            availableScoreSteps--;
            currentScore++;
        }
        currentLevel++;
        availableScoreSteps = currentLevel;
    }
}

Now you can access your level via matchingArray[yourscore] and it will return the level.

dome12b
  • 583
  • 11
  • 32
  • Nice one, I'm going to go with the array because it's a mobile game and I want as little in game processing as possible. – armegalo Jun 25 '18 at 16:46
  • Unless you have enormous arrays or amount of points the processing cost is negligible compared to what is going around. Its good that you consider such things but in general readability is more important. I would choose the technique that makes the most sense for you. – pseudoabdul Jun 26 '18 at 00:59
1

Try this

int maxLevel = 10;

int GetLevel(int points) 
{
    int maxPointsPerLevel = 0;

    for(int level=1; level<maxLevel; level++) {
        maxPointsPerLevel  += level;
        if(points <= maxPointsPerLevel )
        {
            return level;
        }
    }

    return maxLevel;
}
Fredrik Widerberg
  • 3,068
  • 10
  • 30
  • 42
1

Here is a pretty sexy algorithm. Don't feel ashamed, I've never seen anything like this before and I had to sit down with some paper to suss it out. If you find while loops a bit gross, you could pull it off with recursion.

protected int GetLevel(int points)
{
    int i = points;
    int s = 0;
    while(i > 0)
    {
        s++;
        i -= s;          
    }
    return s;
}

Hope that helps!

pseudoabdul
  • 616
  • 3
  • 12