I got the first section of the script figured out :

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class RandomRoleAssignment : MonoBehaviour {

```
public GameObject[] Players;
string[] possibleRoles = {"Citizen" , "Mafia"};
void Start()
{
Players = GameObject.FindGameObjectsWithTag ("Player");
AssignRole ();
}
void AssignRole()
{
int randomRoleIndex = UnityEngine.Random.Range (0, possibleRoles.Length);
string assignedRole = possibleRoles [randomRoleIndex];
for (int i = 0; i < Players.Length; i++)
{
print("Player " + i + " is named " + assignedRole);
}
}
```

}

this script finds all the players with the tag “player” and assigns it the same role. This isn’t what I want it to do, I want it to randomly assign the players either citizen or mafia.

Further I want there to always be a set number of players assigned as mafia (for example if there are 4 players then 1 must be a mafia, if there are 10 players then 2 have to be mafia etc)

So basically you want 25% of your players to be mafia while the remaining 75% are citizen.

Best way is to leave it to probability:

```
if(Random.Range(0,100)< 25)
{
// Player is mafia
}
else
{
// Player is citizen
}
```

Now because probability is almost certain (it’s math), this has to work. Though there is also a probability that you get 100% of one or the other (though extremely not probable).

You could convince yourself with something like this:

```
IEnumerator RandomCoroutine()
{
int mafia = 0; int citizen = 0; int total = 0;
while (true)
{
total += 100;
for (int i = 0; i < 100; i++)
{
if (Random.Range(0, 100) < 25) { mafia++; }
else { citizen++; }
}
int mafiaPerc = Mathf.FloorToInt(((float)mafia / (float)total) * 100f);
int citizenPerc = Mathf.FloorToInt(((float)citizen / (float)total) * 100f);
Debug.Log($"mafia : {mafiaPerc}%, citizen : {citizenPerc}%");
yield return new WaitForSeconds(0.5f);
}
}
```

You will see the printing lurking around 25% and 75%.

One solution is that …to make it easy ,just simply not to assign the random role to player but assign random player to role.

```
public GameObject[] Players;
string[] possibleRoles = {"Citizen" , "Mafia","something else"};
private float[] rolePercent = {0.25f,0.30f};
void Start()
{
Players = GameObject.FindGameObjectsWithTag ("Player");
AssignRole ();
}
void AssignRole()
{
//make an array to record the number of each role,
int[] roleNumber = new int[possibleRoles.Length];
//the last role is full at first.
roleNumber[possibleRoles.Length - 1] = Players.Length;
for (int roleId = 0; roleId < possibleRoles.Length-1; roleId++){
roleNumber[roleId] = Mathf.RoundToInt(Players.Length * rolePercent[roleId]);
//each time we calculate the number of a role,we minus the last role's number to fit the total player's number.
roleNumber[possibleRoles.Length - 1] -= roleNumber[roleId];
}
//to record current player array's random size.
int length = Players.Length;
for (int roleId = 0; roleId < possibleRoles.Length; roleId++){
for (int i = 0; i < roleNumber[roleId]; i++){
int randomPlayerIndex = UnityEngine.Random.Range (0, length);
Debug.Log("Player " + Players[randomPlayerIndex].name + " is named " + possibleRoles[roleId]);
//remove the player simply just make its value equals to last of the array
Players[randomPlayerIndex] = Players[--length];
}
}
}
```

It’s mathematically work.Of course you can make the role assign to player as well,just record the number already given

once encounter the situation where the role you randomly picked is full.roll again .But these will cause a mathematically dead loop if you are very very very unlucky(:

to avoid this mathematical dilemma,you can just plus 1 to index you picked and this will cause some level of recursively check if you are very unlucky as well.

yet I think there must be a neat solution.But i don’t know.