Rerolling RPG Character Attributes With Limits

Hey, guys. I’m attempting to make an RPG character creation screen with a button, allowing you to randomize your characters’ attributes. The problem is, I would like them to be randomized with a limit. For example, if they have 500 points to divide between 10 attributes, I’d like it to randomize those 500 points, and not any more, or any less.

Here’s what I’ve tried so far:
First attempt:

if(GUI.Button (new Rect(800, 500, 50, 50), "Reroll")) {
	Attribute_Points = 0;
	Invested_Attribute_Points = 490;
	for(int cnt = 0; cnt < Enum.GetValues(typeof(AttributeName)).Length; cnt++) {
		_PlayerCharacter.GetPrimaryAttribute(cnt).BaseValue = 1;
		int randatt = UnityEngine.Random.Range (1, 100);
		if(Invested_Attribute_Points > 0) {
			_PlayerCharacter.GetPrimaryAttribute(cnt).BaseValue = _PlayerCharacter.GetPrimaryAttribute(cnt).BaseValue + randatt;
			Invested_Attribute_Points = Invested_Attribute_Points - randatt;
		}

	}
	Debug.Log (Invested_Attribute_Points);
}

This one worked ok, but it always returned a leftover point value between -150, to 150. So it’s not quite good enough.

Second attempt:

   Attribute_Points = 0;
		Invested_Attribute_Points = 490;
		while(Invested_Attribute_Points > 0)
		for(int cnt = 0; cnt < Enum.GetValues(typeof(AttributeName)).Length; cnt++) {
			_PlayerCharacter.GetPrimaryAttribute(cnt).BaseValue = 1;
			int randval = UnityEngine.Random.Range(1, 2);
			if(randval > 1) {
				_PlayerCharacter.GetPrimaryAttribute(cnt).BaseValue++;
				Invested_Attribute_Points--;
			}
		}

I’m sure this second one would have worked, had it not caused the engine to crash with the ridiculous number of calculations.

I’ve tried one or two more things, but I got the same results as my first try at it. I’d greatly appreciate any help.

Thanks to the help of BoredMormon, my problem is solved. Here’s the solution I decided on:

                    Attribute_Points = 0;
			RemainingPoints = 400;

			for(int cnt = 0; cnt < Enum.GetValues(typeof(AttributeName)).Length; cnt++) {
				_PlayerCharacter.GetPrimaryAttribute(cnt).BaseValue = 10;
				int randatt = UnityEngine.Random.Range (0, 50);
					_PlayerCharacter.GetPrimaryAttribute(cnt).BaseValue = _PlayerCharacter.GetPrimaryAttribute(cnt).BaseValue + randatt;
					RemainingPoints = RemainingPoints - randatt;
				
			}
			while(RemainingPoints > 50) {
				for(int cnt = 0; cnt < Enum.GetValues(typeof(AttributeName)).Length; cnt++) {
					int randatt = UnityEngine.Random.Range (0, 5);
					if(RemainingPoints > 0) {
						_PlayerCharacter.GetPrimaryAttribute(cnt).BaseValue = _PlayerCharacter.GetPrimaryAttribute(cnt).BaseValue + randatt;
						RemainingPoints = RemainingPoints - randatt;
					}
				}
			}
			while(RemainingPoints > 0) {
				for(int cnt = 0; cnt < Enum.GetValues(typeof(AttributeName)).Length; cnt++) {
					if(RemainingPoints > 0){
						_PlayerCharacter.GetPrimaryAttribute(cnt).BaseValue++;
						RemainingPoints--;
					}
				}
			}

It works great. Satisfies every parameter I wanted. Again, thanks a ton!

Your second script crashed due to an infinite loop. Random.Range is max exclusive. So it was always returning one in your code. Meaning your if condition never entered, and hence your loop never finished. The number of calculations was trivial. Changing line 6 to

int randval = UnityEngine.Random.Range(1, 3);

or better change line 7 to

if (UnityEngine.Random.value > 0.5f)  

will make it work as written. However you will find the distribution provided by this method to be mind numbingly flat.

You could produce a better distribution by adding about a third of your points every pass. Once you have completed all three passes then loop through and add or subtract points evenly to make your target score.