ID:2213178
 
Code:
    list/IronThrone = list("","","","","","")

IronThrone[1]=player;

for(var/i = 1; i<=6; i++)
if(i<=IronThrone.len)
while(!IronThrone[i] && i<IronThrone.len)
IronThrone.Remove(IronThrone[i])
// if(!IronThrone[i] && i==IronThrone.len)
// IronThrone.Cut(i,0)


Problem description:

IronThrone is a list 6 long. If I have a player in slots 2-6, then the above code trims out all unused slots, leaving a list 1 long with just the player in it.

If the player is in slot 1 (IronThrone[1]) then I get left with a list 2 long, with the player and 1 blank slot.

If I change the while() loop to
while(!IronThrone[i] && i<=IronThrone.len)

then I get a List Out Of Bounds error.

The only way to ensure I get a list just 1 long with just the player in is to uncomment the commented section.

My question is: why? This list 'arithmetic' is confusing me seriously. I'm glad I can get it to work, but I'd much prefer to know why.


I'll just leave this here.

while(IronThrone.Remove(null))


Also, you should ask yourself why you are getting empty spaces in lists in the first place.

You should not be forcibly deleting objects that you know are still in a list. If you can't know which lists the objects are in, you should be keeping track.

In fact, manual deletion of objects should almost never be done at all in DM, because it is insanely slow and often results in errors like the one you are attempting to solve.

Learn how garbage collection works and keep track of your references. You should never have to cull null references from your lists.
So I made the list six long because there are six 'teams' that can be chosen from by the players. Each team has certain positions they naturally occupy in the list, but if not all teams are in play then the lists aren't filled.

I'm not deliberately trying to destroy "objects" (I assume you're using that word conceptually and not literally as "obj"?) - just spaces left unfilled after teams have been picked.

Also, I've been away from DM for a couple years, so I'm rustier than the tin-man before Dorothy sorted him out. Apologies.
Mayhap this 'context' might shed some light on my naive attempt at this:

        for(var/players in Players)
var/mob/Player/player = Players[players]
if(player)
if(player.House=="Stark") {IronThrone[3]=player; Fiefdoms[4]=player; Raven[2]=player;}
else if(player.House=="Lannister") {IronThrone[2]=player; Fiefdoms[6]=player; Raven[1]=player;}
else if(player.House=="Baratheon") {IronThrone[1]=player; Fiefdoms[5]=player; Raven[4]=player;}
else if(player.House=="Tyrell") {IronThrone[6]=player; Fiefdoms[2]=player; Raven[5]=player;}
else if(player.House=="Greyjoy") {IronThrone[5]=player; Fiefdoms[1]=player; Raven[6]=player;}
else if(player.House=="Martell") {IronThrone[4]=player; Fiefdoms[3]=player; Raven[3]=player;}
//Shuffle everyone up - reduce list length to number of Players
for(var/i = 1; i<=6; i++)
if(i<=IronThrone.len)
while(i<=IronThrone.len && !IronThrone[i])
IronThrone.Remove(IronThrone[i])
if(i<=Fiefdoms.len)
while(i<Fiefdoms.len && !Fiefdoms[i])
Fiefdoms.Remove(Fiefdoms[i])
if(i<=Raven.len)
while(i<Raven.len && !Raven[i])
Raven.Remove(Raven[i])
There is very likely a much cleaner data structure you could be using, but that code doesn't really make much sense out of context.
So to single out the IronThrone list.

I'd like any number of players between 1 and 6 to be able to play. Each must pick their own House, and no-one can pick the same as anyone else.

If someone picks "Baratheon" then they'd be first in the list, then Lannister, then Stark, e.t.c.

If Lannister were absent (i.e., there are only five players) then Baratheon would remain first but then Stark would be second.
var/list/houses = list("Lannister","Baratheon","Stark","Tyrell","Greyjoy","Martell")
var/list/players = list()


When a player picks a house:

houses[house] = M
M.house = house
players += M


Checking if a house has already been taken:

if(houses[house]) //house is taken
if(!houses[house]) //house is not taken


Use the players list to iterate over active players. The players list is a plain-Jane array.

Use the player's house variable to figure out which house they are. The player's house variable stores the string name of the house.

Use the houses list to get the player by house name where you need to. Houses is an associative list with strings as keys and players or null as values.


Your logic is just being overcomplicated by using the houses list to serve the same function as the players list. Keep two lists separate instead. It simplifies the logic. You never need to remove the unused houses from the houses list because it's only a lookup table for which houses have players.
My houses lists only serves to store the starting positions of each player on each track. After that initial set up it's never used again.

Then for all intents and purposes, IronThrone[] is my players[] list. It dictates turn order, hence the initial set up based on the chosen House, and is then iterated through for game turns.

The other order of the players on the other two lists is also important, (one dictates advantage in battles, the other provides special abilities), so I can't remove them either.

<edit> The Players[] list at the top of the code snippet is just a temporary holding place whilst in the lobby, before the game has started, and isn't used afterwards. It is going to be repurposed to hold all players and all spectators at some point, but I haven't gotten around to it.</edit>