Find specific string in ds_list and replace some value

D

dboholst

Guest
Hello,
I'm making a real time Ranking System that is drawn in screen during gameplay, but for the life of me I could not find anything.
I want to change the score but my script just constantly add a new entry in the list with the same player with different score.
Please help
Code:
//DRAW
for (var i=0;i<ds_list_size(score_list)-1;i++)
{
    ds_list_sort(score_list,false);
    var txt = string(ds_list_find_value(score_list,i));
    var xx    = 20;
    var yy    = 13 * (i*1.5);
    if (i=0) //LEADING PLAYER
    {
        DrawSetText(c_yellow,1,Ort_small,fa_left,fa_top);
        draw_text(xx,yy+35,string_upper(txt));
    }
    else    //OTHER PLAYERS
    {
        DrawSetText(c_white,1,f_score,fa_left,fa_top);
        draw_text(xx,yy+40,string_upper(txt));
    }
}
GML:
function AddScore(_score,_name){

    var str = ds_list_find_index(score_list,_name);
    if (!is_string(str))
    {
        var item = string(_score)+" - "+_name;
    
        if (ds_list_size(score_list) < 10)
        {
            ds_list_add(score_list,item);
        }
        else
        {
            ds_list_delete(score_list,10);
            ds_list_add(score_list,item);
        }
    }
}
 

Nidoking

Member
Well, for starters, you don't want to sort the list in the Draw event, and DEFINITELY not inside a loop. Just sort it when you update it.

ds_list_find_index returns the index of the entry in the list. Why would that ever be a string? Also, since the entries in the list are score + name, the entry will never be just name.

ds_list_add adds to the list, hence the name "ds_list_add". You're always adding a new entry and never updating the old entries. Did you think you were using a map?

I think you need to read the Manual pages for every function you used here. I don't think you got any of them quite right.
 
D

dboholst

Guest
Thank you for the advice, I'll work on those. But I still need to figure out how to find and overwrite some of the entries.
 

Nidoking

Member
You'll probably have to do substring searches if you want to find just matching names. And you assign values with =, same as anything else.
 
D

dboholst

Guest
I think I may have figured it out, except that every now and then the sorting would fail to hit as you can see in the picture.
GML:
function AddScore(_score,_name){
    if (!ds_exists(score_list,ds_type_list))
    score_list = ds_list_create();

    var check_name = ds_list_find_index(score_list,_name);
    if (check_name)
    {
        ds_list_replace(score_list,check_name-1,_score);
    }
    else
    {
        var last_entry = 6;
        if (ds_list_size(score_list) < last_entry)
        ds_list_add(score_list,string(_score)+"-"+_name);
        else
        ds_list_set(score_list,last_entry-1,string(_score)+"-"+_name)
        

    }
    //sort the Score_list
    ds_list_sort(score_list,false);

}
Code:
//Draw
for (var i=0;i<ds_list_size(score_list)-1;i++)
{
    var txt    = string(ds_list_find_value(score_list,i));
    var xx    = 20;
    var yy    = 13 * (i*1.5);
    if (i=0) //LEADING PLAYER
    {
        DrawSetText(c_yellow,1,Ort_small,fa_left,fa_top);
        draw_text(xx,yy+35,string_upper(txt));
    }
    else    //OTHER PLAYERS
    {
        DrawSetText(c_white,1,f_score,fa_left,fa_top);
        draw_text(xx,yy+40,string_upper(txt));
    }
}
 

Attachments

chamaeleon

Member
Maybe it becomes simpler using a grid. In this case I'm assuming the use of 5 high-scores to be displayed, and use a a grid 6 rows high. When a score is added, I add it last, then sort the grid. The 6th row is not used for anything besides the temporary storage of content for the purpose of potentially sorting the new score up in the list (leaving some other row last, that will be overwritten the next time a score is added).
Create event
GML:
game_scores = ds_grid_create(2, 6);

for (var i = 0; i < 6; i++) {
    game_scores[# 0, i] = 0;
    game_scores[# 1, i] = "BLANK";
}
GML:
// Simulate Foo getting 10 points
game_scores[# 0, 5] = 10; game_scores[# 1, 5] = "Foo";
ds_grid_sort(game_scores, 0, false);
// Simulate Bar getting 5 points
game_scores[# 0, 5] = 5; game_scores[# 1, 5] = "Bar";
ds_grid_sort(game_scores, 0, false);
// Simulate Baz getting 20 points
game_scores[# 0, 5] = 20; game_scores[# 1, 5] = "Baz";
ds_grid_sort(game_scores, 0, false);
Draw event
GML:
for (var i = 0; i < 5; i++) {
    draw_set_color(i == 0? c_yellow : c_white);
    draw_text(20, 100+32*i, string_format(game_scores[# 0, i], 2, 0) + " = " + game_scores[# 1, i]);
}
Text drawn in game window looks somewhat like the below
Rich (BB code):
20 = Baz
10 = Foo
 5 = Bar
 0 = BLANK
 0 = BLANK
 
D

dboholst

Guest
THIS IS FANTASTIC!
And seems effortless, here I was pulling my hair yesterday.
Thank you!
 
D

dboholst

Guest
The only caveat is it duplicates entry, like I will get 2 foo or 3 bar, so on..
I tried to mitigate this by searching existing name in the grid and changing the score, sometimes it doesn't register.
GML:
        //GET POSITION OF EXISTING ENTRY
        var ypos = ds_grid_value_y(game_scores, 0, 0, 2, 6, _name);
            
        if (ypos)//UPDATE SCORE ON EXISTING ENTRY
        {
            if (game_scores[# 0, ypos] < _score)
            game_scores[# 0, ypos] = _score;
        }
        else//NEW ENTRY
        {
            game_scores[# 0, 5] = _score;
            game_scores[# 1, 5] = _name;
        }
        ds_grid_sort(game_scores, 0, false);
 

chamaeleon

Member
The only caveat is it duplicates entry, like I will get 2 foo or 3 bar, so on..
I tried to mitigate this by searching existing name in the grid and changing the score, sometimes it doesn't register.
GML:
        //GET POSITION OF EXISTING ENTRY
        var ypos = ds_grid_value_y(game_scores, 0, 0, 2, 6, _name);
         
        if (ypos)//UPDATE SCORE ON EXISTING ENTRY
        {
            if (game_scores[# 0, ypos] < _score)
            game_scores[# 0, ypos] = _score;
        }
        else//NEW ENTRY
        {
            game_scores[# 0, 5] = _score;
            game_scores[# 1, 5] = _name;
        }
        ds_grid_sort(game_scores, 0, false);
ypos will be -1 when the name is not found. 0 is the index of the first entry. 0 is also treated as false and will therefore not update the first entry if that is where the name is found.
GML:
...
    if (ypos != -1)
    {
        ... update entry ...
    }
    else
    {
        ... new entry ...
    }
...
 
Top