• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Change an element position inside ds_list

waliente

Member
Hi at all!

I've an issue... i need to change position between elements inside a pre-created ds_list.

I have a charactersList that is a ds_list created before the code below with a randomic position of the elements. During the step event of an object called oTurnManager i have to check the order of the characters based on an instance variable called "isOverlord: Boolean".


GML:
for (var i = 0; i < charactersList; i++) {
    _inst = ds_list_find_value(global.characters, i);

    if (_inst[0].isOverlord) {

    }
}
At the condition that the instance has the isOverlord variable set to true, i need to change his position at index 0... How can i do that?
 

samspade

Member
Hi at all!

I've an issue... i need to change position between elements inside a pre-created ds_list.

I have a charactersList that is a ds_list created before the code below with a randomic position of the elements. During the step event of an object called oTurnManager i have to check the order of the characters based on an instance variable called "isOverlord: Boolean".


GML:
for (var i = 0; i < charactersList; i++) {
    _inst = ds_list_find_value(global.characters, i);

    if (_inst[0].isOverlord) {

    }
}
At the condition that the instance has the isOverlord variable set to true, i need to change his position at index 0... How can i do that?
This code seems to have a couple issues. A list holds only one value, so what is the value the list holds? It seems like it is instance id. If that is the case then what you would want is this:

GML:
for (var i = 0; i < charactersList; i++) {
    _inst = ds_list_find_value(global.characters, i);

    if (_inst.isOverlord) {

    }
}
What you wrote treats _inst, the value returned from the array, as an array. If it was an array, then you would want the check to be if (_inst[0] == isOverlord). (Your code would be correct if _inst was an array that held a struct at the 0th position, but that seems unlikely).

I also don't understand this sentence: " i need to change his position at index 0" Does that mean you want the overlord to be the first instance in the list? Or something else?

As a side note, the fact that you're checking length in the array with charactersList but using searching a global.characters is a little concerning. Is characters list a list or the length of a list. If the first, I'm surprised this works at all, if the second, I'd suggest a different name.
 

waliente

Member
Oh... you have right i made a mistake here that i fix after this post, and now the code is:

GML:
for (var i = 0; i < charactersList; i++) {
    _inst = ds_list_find_value(global.characters, i);

    if (_inst[0].isOverlord) {

    }
}


I also don't understand this sentence: " i need to change his position at index 0" Does that mean you want the overlord to be the first instance in the list? Or something else?
Yes i mean that the overlord should be the first of the list...



As a side note, the fact that you're checking length in the array with charactersList but using searching a global.characters is a little concerning. Is characters list a list or the length of a list. If the first, I'm surprised this works at all, if the second, I'd suggest a different name.
Yes charactersList is a list's size... as you can see below:

GML:
charactersList = ds_list_size(global.characters);

So what i need is during the loop switch Overlord position always as the first element of the ds_list global.characters, and obviously switch the previous first character of the list at the previous position of Overlord instance or going at the second position after the Overlord....

Thank you :)
 

TheouAegis

Member
Why is _inst being treated as an array? Isn't it just the id of a single instance?

Just delete index i from the list and insert _inst at index 0.
 

waliente

Member
After couple of days i've made some changes to my code and now the situation is:
  • I have an init() function inside the oController object where i instantiate the global.characters = ds_list_create().
  • in oController i have the generateCharacters() function that add elements to the ds_list and draw the character with assigned sprite and options.
  • then i have an oTurnManager where i have at the create event the setTheOverlord() function
  • Actually my setTheOverlord code is:
GML:
function setTheOverlord(_incomingInstance){
    
    randomize();
    var _inst        = _incomingInstance;
    var _listSize    = ds_list_size(global.characters);
    var _random        = irandom_range(0, (_listSize - 1));
    
    if (not _inst) {
        _inst = ds_list_find_value(global.characters, _random);
        show_debug_message("Overlord is: " + _inst.charName);
    }
    
    _inst.sprite_index = asset_get_index("s" + _inst.charName + "Overlord");
    _inst.isOverlord = true;
    
    var _firstElement = ds_list_find_value(global.characters, 0);
    var _instPosition = ds_list_find_index(global.characters, _inst);
    
     ds_list_set(global.characters, 0, _inst);
     ds_list_set(global.characters, _instPosition, _firstElement);
    
    //ds_list_delete(global.characters, 0);
    //ds_list_delete(global.characters, _instPosition);
    //ds_list_insert(global.characters, 0, _inst);
    //ds_list_insert(global.characters, _instPosition, _firstElement);
    
}
After that the results isn't what i need.. If you see i've commented out the delete and the insert because gives me unexpected results, and with the _set is the same..

What I want to achieve is to set the instace with isOverlord true at the first position of the global.characters ds_list... but this code still not working :(

Thank you for help and attention! :)
 

Nidoking

Member
You have to delete the last one first. When you delete element 0, everything shifts to the left one position to fill in the gap.
 

waliente

Member
Are you suggesting to do as i commented in the code?
GML:
//ds_list_delete(global.characters, 0);
//ds_list_delete(global.characters, _instPosition);
//ds_list_insert(global.characters, 0, _inst);
//ds_list_insert(global.characters, _instPosition, _firstElement);
This way?
 

Nidoking

Member
No. That is, in fact, exactly the opposite of what I'm saying to do. I'm saying that if you delete element 0, then the _instPosition that you found is no longer valid, because the list has one less element at the start and all of the indices have shifted, so the element at position _instPosition is no longer the element that was there when you got the value of _instPosition, but a different element entirely or perhaps no element at all, if _instPosition was the last element of the list. My suspicion was that that was the reason you said it "still not working", and I think your question has just proven me correct. You need to reorder your steps if you're going to delete and insert, so that the indices are correct based on what elements are in the list at the time. The set commands, on the other hand, should be working properly. If it's not, then your description of HOW or WHY it's not working is lacking. And by lacking, I mean you haven't provided one, so I hope you weren't expecting any help, because you're not getting any.
 

waliente

Member
Ok now is more clear the position's issue. But there isn't raeson to attack me in this way. I'm quite new about GML and i'm understanding ds_lists about few weeks. Can i ask doubt or help? Or is forbidden?

Thank you for the help and clarification. I'll do my best.
 

Nidoking

Member
Can i ask doubt or help?
Of course! But there needs to be a question. This:
this code still not working
doesn't describe a problem. It simply says that you have a problem. Okay, you have a problem. I have problems too, but nobody can help me if I don't tell them what the problems are. This is not an issue with your understanding of GML, but in the amount of detail that you are providing that might help people figure out what your problem is, which is required if anyone is to help you. That's not an attack; it's a fact. If you don't want help, then that's fine. Good luck fixing the problem. But if help is what you want, then you've got to meet us halfway.
 

waliente

Member
Before you telling me the position's issue, i haven't realized the problem... and if i say this code that i made with the forum's users help not working not because the code is wrong but surely because i'm doing something wrong... this for me is implied. And if i re-post the situation is for understand my errors from the more experienced users.
While i've posted this i've watched a lot of video about ds_list to understand better the data structure, but i'm still not a professor...
I tried to report as many details possibile in my posts to better understand the situation....
 

Nidoking

Member
not because the code is wrong but surely because i'm doing something wrong
That really doesn't make any sense. If you're doing something wrong, then the result is incorrect. How can the code not be wrong? If you mean that there's some other setting in your game that's wrong rather than the code... hey, guess what? That's also part of your game! It's a thing that can be fixed! If you know how to fix it, good. If you can figure out how to fix it, good. If you can't figure out how to fix it, and you're not asking because you feel some kind of shame or guilt about asking, then the result is a broken game that doesn't get fixed. You can have more than one problem, you know. Fixing one thing doesn't mean that everything will magically work.

And if i re-post the situation is for understand my errors from the more experienced users.
I don't follow your sentence structure here. Are you saying that you want more experienced users to help you understand the errors? Well, they can't, because you haven't described the errors. You just say "still not working". Does the game crash? Does it run, but do something that you don't want it to do? What is the thing that it does? If you're just posting to see your own words in print and hoping that something will jump out at you... well, okay, but it still might help to actually describe the problem at the same time.

i'm still not a professor
Those who can, do. Those who can't, teach. Nobody expects you to be a professor, except maybe you. Learning is a good thing. Do lots of it. But at the same time, you put a frowny face emoji. To me, that says that you're sad that your game doesn't do what you want. I'm sad too, but I can't help you.

I tried to report as many details possibile in my posts to better understand the situation....
unexpected results
still not working
I'm sure more details are possible. There's always more than zero.
 
So lists might seem complicated at first, because of having to learn new commands to deal with them, but in reality they are very simple. Just think of a literal list in real life. Let's say you have a list with 5 points on it:

1. A
2. B
3. C
4. D
5. E

You want to find wherever D is in the list and move it to the top spot. The steps you would take as a human (often unconsciously) are:

Scan the list to find which position has D in it.
You've found D and it's at the 4th slot.
Keep in your memory that the data you are moving is D.
Erase position 4 with your eraser.
Write D at the top of the list and give it the position 1.
Rewrite all the other position numbers accordingly.

When you're dealing with that in code some of those steps you have to do and some the computer will do for you. Specifically the rewriting of the positions, the last step above, will be done automatically by the computer, but the rest of the steps you have to do yourself.

So, based off your updated code posted on Saturday, you already have the instance you want stored in the _inst variable before you need to rearrange the list. So let's have a look at the problem code:
Code:
var _firstElement = ds_list_find_value(global.characters, 0);
var _instPosition = ds_list_find_index(global.characters, _inst);
    
ds_list_set(global.characters, 0, _inst);
ds_list_set(global.characters, _instPosition, _firstElement);
First of all, you don't need to know what's in the first place, so there's no need for this line var _firstElement = ds_list_find_value(global.characters, 0); (remember none of the steps that I wrote out that you would take as a human involves finding what value is in the first position). So let's go ahead and rewrite that block so it functions properly:
Code:
var _instPosition = ds_list_find_index(global.characters, _inst);

ds_list_delete(global.characters,_instPosition); // First we delete the position that holds the _inst value, we do this first because if we insert the position first, the list order will change and _instPosition will no longer point to the correct position  
ds_list_insert(global.characters, 0, _inst); // Then we use the ds_list_insert() function to place a value at a position, not ds_list_set as ds_list_set will overwrite whatever is stored in position 0 currently
And that should be it. When you're dealing with these things in the future, make sure to read through the manual and ALL the entries that are involved with whatever you are dealing with. Looking just at ds_list_set() would not yield the answers you need, but looking at the ds_lists page and reading each function listed there, you should be able to, with a bit of experimentation and some time thinking, figure out what the functions you need to use are. Then it's just a matter of using code logic in your head to place them in the correct positions.
 
Top