Problem referencing dictionaries nested in other dictionaries

Hello, I am trying to make a sort of “Mafia” game where the computer auto-assigns roles for everyone. I have dictionaries nested inside of other dictionaries to help me, but I’m having trouble referencing to get the values that I need. The roles according to player count is just to choose how many of each role there needs to be for Five, Six, Seven, or Eight players. The player roles table is just to keep the the players in a neat fashion, having arrays in the dictionaries that contain the players. If there’s an easy way to reference dictionaries nested in other dictionaries then it would be great to know. Thanks!

if #game.Players:GetChildren() >= 5 then
	if gamemode == "Automatic" then
		local playerRoles = {
		Mafia = {},
		Host = {},
		Sherrif = {},
		Doctor = {},
		Towny = {}
		}
		local rolesAccordingToPlayerCount = {
		Five = {Mafia = 1, Host = 1, Sherrif = 1, Doctor = 0, Towny = 1},
		Six = {Mafia = 1, Host = 1, Sherrif = 1, Doctor = 1, Towny = 2},
		Seven = {Mafia = 1, Host = 1, Sherrif = 1, Doctor = 1, Towny = 3},
		Eight = {Mafia = 1, Host = 1, Sherrif = 2, Doctor = 1, Towny = 3},
		}
		
		if numPlayers == 5 then
			numPlayersInWords = "Five"
		elseif numPlayers == 6 then
			numPlayersInWords = "Six"
		elseif numPlayers == 7 then
			numPlayersInWords = "Seven"
		elseif numPlayers == 8 then
			numPlayersInWords = "Eight"
		end
		
		for key,value in pairs(playersToAssign) do
			 for k,v in pairs(rolesAccordingToPlayerCount[numPlayersInWords]) do -- looping through table of number of roles left according to player count
				if v["Mafia"] >= 1 then
					v["Mafia"] = v["Mafia"] - 1
					for i,player in pairs(playersToAssign) do
						if playersToAssign[i] == player then
							table.remove(playersToAssign,i) -- finding value of player in table and removing them
							table.insert(playerRoles["Mafia"],1,player)
						end
					end
				elseif v["Host"] >= 1 then
					v["Host"] = v["Host"] - 1
					for i,player in pairs(playersToAssign) do
						if playersToAssign[i] == player then
							table.remove(playersToAssign,i) -- finding value of player in table and removing them
							table.insert(playerRoles["Host"],1,player)
						end
					end
				elseif v["Sherrif"] >= 1 then
					v["Sherrif"] = v["Sherrif"] - 1
					for i,player in pairs(playersToAssign) do
						if playersToAssign[i] == player then
							table.remove(playersToAssign,i) -- finding value of player in table and removing them
							table.insert(playerRoles["Sherrif"],1,player)
						end
					end
				elseif v["Doctor"] >= 1 then
					v["Doctor"] = v["Doctor"] - 1
					for i,player in pairs(playersToAssign) do
						if playersToAssign[i] == player then
							table.remove(playersToAssign,i) -- finding value of player in table and removing them
							table.insert(playerRoles["Doctor"],1,player)
						end
					end
				elseif v["Towny"] >= 1 then
					v["Towny"] = v["Towny"] - 1
					for i,player in pairs(playersToAssign) do
						if playersToAssign[i] == player then
							table.remove(playersToAssign,i) -- finding value of player in table and removing them
							table.insert(playerRoles["Towny"],1,player)
							print("Inserted player " .. player.Name .. " to role Towny")
						end
					end
				end
			end
		end
	end
end

If you need the error that it gave, it said “attempt to index number with ‘Mafia’”.

1 Like

You have your keys and values mixed up. In the line

for k,v in pairs(rolesAccordingToPlayerCount[numPlayersInWords]) do

the key (k) is each of your roles and the value (v) is the number of each of those roles. By doing v["Mafia"] you are essentially trying to index a number with the key “Mafia” which will throw an error. Armed with this knowledge I’m sure you’ll be able to figure out a way to fix your code. If not then just ping me.

Hint: Check whether each key is the role you want and then the corresponding value can be compared and manipulated.

@WizardlyShadow Would something like this work?

for key,value in pairs(playersToAssign) do
			 for k,v in pairs(rolesAccordingToPlayerCount[numPlayersInWords]) do -- looping through table of number of roles left according to player count
				if k == "Mafia" then
					if v >= 1 then
						v = v - 1
						for i,player in pairs(playersToAssign) do
							if playersToAssign[i] == player then
								table.remove(playersToAssign,i) -- finding value of player in table and removing them
								table.insert(playerRoles["Mafia"],1,player)
							end
						end
					end
				end
			end
		end

You’re only changing the value of v in this case, which means it won’t change in your dictionary.

To make things more readable I’m going to assign the dictionary that you will loop through to a variable.

local currentDictionary = rolesAccordingToPlayerCount[numPlayersInWords]
for key,value in pairs(playersToAssign) do
	for k,v in pairs(currentDictionary) do -- looping through table of number of roles left according to player count
		if k == "Mafia" then
			if currentDictionary["Mafia"] >= 1 then --get the value stored in the dictionary to manipulate it
				currentDictionary["Mafia"] = currentDictionary["Mafia"] - 1
               --rest of your code here
			end
		end
	end
end

@WizardlyShadow I have changed everything, but the “if k == “Mafia”” is not going through so it is just skipping it and not doing anything.

1 Like

Try not to nest more dictionaries and create more keys as this would make things much harder for you. Instead try making your values more accessible.

There’s nothing wrong with nesting dictionaries. Especially in a case such as this nothing is being made more difficult.

@ElusiveEpix Not sure what you want me to do. If there are no errors or anything you should try manually debugging your script with print statements to see what the value of ‘k’ and other variables are. Also you should be attempting to solve the problem on your own rather than constantly coming back here asking for handouts.

I’m talking about the accessibility. More keys > More values to index > More tables to loop and More to manage. Which makes it more complex and therefore making things much harder.