• 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!

GameMaker Search for ds_map value

B

blabluxd

Guest
Hello :) ,

I have a question over a code I am breaking my head over for several days now!
I have this line of code where you get different rewards depending on the number. For example if you win coins, you get +100 coins etc.

In this case you win a new football. I have a ds_map that stores 20 footballs under the ID "Football1", "Football2" and so on. They all store the value 0 for locked and 1 for owned. When you run the game for the first time the ds map gets created and the player owns only "Football 1".

Code:
ini_open("saveData.ini");
    if (ini_read_real("Game", "OpenedForFirstTime", 1) == 1) {
        ini_write_real("Game", "OpenedForFirstTime", 0);
       
    // create the ds map for footballs
    global.footballs = ds_map_create();
    // add all footballs as locked
    for (var i = 1; i < number_of_footballs; i++) // Check star count and save in 1D array
    {
      ds_map_add(global.footballs, "Football"+string(i), 0);
    }
   
    // change football 1 as unlocked
    ds_map_replace(global.footballs, "Football1", 1);
}
Now when winning a football, the game should choose a random ball and check if its locked and then make it owned. So change the value from 0 to 1. If the ball has the value 1 already, so it is owned already, then it should check for another ball. Thats the part where I'm stuck. I dont know how to search as long until a locked ball is found!

Code:
// get reward for football
if (reward == 192) {
    var random = irandom_range(2,20);
    if (ds_map_find_value(global.footballs, "Football"+string(random)) == 0) {
        ds_map_replace(global.footballs, "Football"+string(random), 1)
    }
I would really appreciate any help :)

greetings
 
C

Catastrophe

Guest
Edit: Late night brainfart, previous suggestion wouldn't work

Yeah, I'd just maintain a ds_list filled with the indices of locked footballs and remove randomly from that as you unlock them.

Alternatively, loop through the ds_map to create such a list of locked footballs on the fly, and pull randomly from that list. ds_map_find_next has an example for how to loop a ds_map in the manual
 
Last edited by a moderator:

TheouAegis

Member
Code:
// get reward for football
if (reward == 192) {
var random = irandom_range(2,20);
if (ds_map_find_value(global.footballs, "Football"+string(random)) == 0) {
ds_map_replace(global.footballs, "Football"+string(random), 1)
}
You're close, but you need to make it a loop.
Code:
var rand = irandom_range(2,20), b = 18;
while b && global.footballs[?"Football"+string(rand)] {
    rand++;
    if rand > 20
        rand = 2;
    b--;
}
if b
    global.footballs[?"Football"+string(rand)]++;
}
Something like that.
 
B

blabluxd

Guest
Edit: Late night brainfart, previous suggestion wouldn't work

Yeah, I'd just maintain a ds_list filled with the indices of locked footballs and remove randomly from that as you unlock them.

Alternatively, loop through the ds_map to create such a list of locked footballs on the fly, and pull randomly from that list. ds_map_find_next has an example for how to loop a ds_map in the manual
Okay thank you, I tried to do it but it doesnt seem to work.
I create two ds_maps now. One for locked balls and one for owned balls. When the game gets launched for the first time it creates all 20 balls in the "locked ds map". Then it takes Football 1, deletes it and creates Football 1 in the "owned ds map".
Code:
ini_open("saveData.ini");
    if (ini_read_real("Game", "OpenedFirstTime", 1) == 1) {
        ini_write_real("Game", "OpenedFirstTime", 0);
       
    // create the ds map for footballs
    global.locked_footballs_map= ds_map_create();
    global.owned_footballs_map = ds_map_create();
    // add all footballs as locked
    for (var i = 2; i < global.number_of_locked_footballs; i++) // Check star count and save in 1D array
    {
      ds_map_add(global.locked_footballs_map, "Football"+string(i), 0);
    }
   
    // change football 1 as unlocked
    ds_map_add(global.owned_footballs_map, "Football1", 1);
    ds_map_delete(global.locked_footballs_map, "Football1");
    global.number_of_locked_footballs --;
    global.number_of_owned_footballs ++;
}
Additionally I added a count for each list to be able to limit the random number that is picked when choosing randomly the price:
Code:
// get reward for football
if (reward == 192) {
    // get a random football
    var randomNumber = irandom_range(0, global.number_of_locked_footballs);
    // delete from locked map
    ds_map_delete(global.locked_footballs_map, "Football"+string(randomNumber));
    global.number_of_locked_footballs --;
    // add to owned map
    ds_map_add(global.owned_footballs_map, "Football"+string(randomNumber), 1);
    global.number_of_owned_footballs ++;
    }
}
And where you can select your balls and see if you got it I have an controller object that creates 20 buttons for each ball:
Code:
var var_instance = instance_create_layer(width, height, "Instances", but_selectBall);
if (ds_map_find_value(global.owned_footballs_map, "Football1") == 1) {
    var_instance.owned = true;
}
else    {var_instance.owned = false;}
var var_instance = instance_create_layer(width*2, height, "Instances", but_selectBall);
if (ds_map_find_value(global.owned_footballs_map, "Football2") == 1) {
    var_instance.owned = true;
}
else    {var_instance.owned = false;}

.... and 18 more times
In the button there is check if owned = 1 you can click on it and get a message that you own the ball. if = 0 then you get an error message. But when I go into this creen there is this error message.
Code:
___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Create Event
for object cnt_select:
global variable name 'owned_footballs_map' index (100047) not set before reading it.
 at gml_Object_cnt_select_Create_0 (line 5) - if (ds_map_find_value(global.owned_footballs_map, "Football1") == 1) {
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Object_cnt_select_Create_0 (line 5)
How can I check if a certain Key is existing? and is the rest like you imagined?
 
B

blabluxd

Guest
N
Edit: Late night brainfart, previous suggestion wouldn't work

Yeah, I'd just maintain a ds_list filled with the indices of locked footballs and remove randomly from that as you unlock them.

Alternatively, loop through the ds_map to create such a list of locked footballs on the fly, and pull randomly from that list. ds_map_find_next has an example for how to loop a ds_map in the manual
OH NEVERMIND! I found the ds_map_exist in the manual... I think my brain is working slow after reading the page for the 10th time! Thank you sir! Ill text my code if it works.
 
C

Catastrophe

Guest
TheouAegis' idea actually also works and is the fastest way of doing it, it's just difficult to understand why. Basically if you pick a random starting point and walk through the numbers, the result is a the same as keep choosing randomly except it's quicker. The 18 (20-2 or the size of the range) is to ensure you walk through all of them, and the (if rand = 20) rand = 2 is so you start at the beginning after walking off the edge. If the b goes to 0, stop and don't add anything since you've went through all of them and didn't find any locked.

Regarding my suggestion, you would not make a second ds_map, but merely a ds_list just for the purpose of determining unlocked items. But either way works :)
 
Last edited by a moderator:
Top