Well, it is difficult to put in GM code, because I don't know exactly what your code is. Thus I'll do it in semi pseudo code But you have the following:
x -> is the number of the current dungeon.
dungeon[x,0] -> number of keys still available to Link
dungeon[x,1] -> temporary status indications that only last as long as Link visits this room cluster.
dungeon[x,2]-[x,4] -> the permanent status of the dungeon.
This is the code to execute a dungeon achievement with the dungeon number and index
flag = ( index div 53 ) + 2
flag_index = index mod 53
dungeon[x,flag] = setFlag(dungeon[x,flag], flag_index);
// Set flag already checks whether it is already set or not.
Let's see if I understand correctly.
show_message(string(dungeon[x,0])) would give me "01010001001..."?
dungeon[x,0] would contain the same data as the array Key_Collected[index] with indicators ranging [0-9]?
It seems elegant if so but we'd need to define clear guidelines for what this data means.
flag = ( index div 53 ) + 2
I assume the first two positions have a special function like keeping track of how many variables are effectively stored.
In my own engine I did something simular:
// Small chest info
Chest_Last = 9;
Chest_Opened[0] = 0; Chest_Floor[0] = 4; Chest_X[0] = 48; Chest_Y[0] = 60; Chest_Master[0] = 0;
Chest_Opened[1] = 0; Chest_Floor[1] = 4; Chest_X[1] = 30; Chest_Y[1] = 46; Chest_Master[1] = 0;
Chest_Opened[2] = 0; Chest_Floor[2] = 4; Chest_X[2] = 88; Chest_Y[2] = 46; Chest_Master[2] = 0;
Chest_Opened[3] = 0; Chest_Floor[3] = 4; Chest_X[3] = 72; Chest_Y[3] = 14; Chest_Master[3] = 0;
Chest_Opened[4] = 0; Chest_Floor[4] = 5; Chest_X[4] = 87; Chest_Y[4] = 14; Chest_Master[4] = 0;
Chest_Opened[5] = 0; Chest_Floor[5] = 4; Chest_X[5] = 46; Chest_Y[5] = 12; Chest_Master[5] = 0;
Chest_Opened[6] = 0; Chest_Floor[6] = 3; Chest_X[6] = 71; Chest_Y[6] = 23; Chest_Master[6] = 0;
Chest_Opened[7] = 0; Chest_Floor[7] = 5; Chest_X[7] = 95; Chest_Y[7] = 14; Chest_Master[7] = 0;
Chest_Opened[8] = 0; Chest_Floor[8] = 4; Chest_X[8] = 58; Chest_Y[8] = 43; Chest_Master[8] = 1;
Chest_Opened[9] = 0; Chest_Floor[9] = 3; Chest_X[9] = 34; Chest_Y[9] = 61; Chest_Master[9] = 1;
The first variable tells how many chests exist (for this area). This is mainly done for the creation of the map since you need to know how long you array is. In your solution this is constant so it's no issue, but I can image though that you won't want to loop through 53 possible chests when you only have one.
This is code that is executed when Link is opening a chest. Note that each chest has a variable denoting the index of the permanent status and a variable to denote whether it is opened or not:
if !chest.opened
chest.opened = true
give Link the contents and if the contents is a small key dungeon[x,0] += 1
setDungeonAchievement(x, chest.index)
Opening a door is similar. It also has a variable opened and an index. Off course when the door is opened by a switch or dungeon puzzle you don't need to bother with checking keys.
if !door.opened and dungeon[x,0] > 0
door.opened = true
setDungeonAchievement(x, door.index)
decrease the number of small keys dungeon[x,0] -= 1
You only need three core variables per chest (for now). What is it's index? Is it opened? What was it contents? I store the second and third high over and the first as a variable as a property of the chest. The chest object is something that gets reset when you exit and enter a Area/Cluster. I'm talking about the entire object and thus the variable attached to it is also constantly reset.
You only need:
if !getDungeonAchievement(x, chest.index)
give Link the contents and if the contents is a small key dungeon[x,0] += 1
setDungeonAchievement(x, chest.index)
When you've opened the chest just delete it while leaving the masking. Or turn it invisible, depending on your preference in masking.
Something simular can be said for the locked doors.
if !getDungeonAchievement(x, door.index) and dungeon[x,0] > 0
setDungeonAchievement(x, door.index)
decrease the number of small keys dungeon[x,0] -= 1
I make a distincion between locked doors and otherwise closed doors, but that's for another day.
I don't know what every array is used for with your code and how much objects play a role in your code and maintain status values about themselves. But I do know that a door that is already opened, cannot take a key again and a chest that has already been opened, a pot that has already given a key cannot provide a key. Thus you don't need to check how many keys are still left or keys that are already spent, because either the chest or door has not been opened.
My point is that with true false status indications, using a single number as a boolean array would be better than having long arrays. It saves in used memory, although PC's have already a lot of memory. When saving this data to a file you only need to save a few numbers instead of an entire array.
I wend about it in somewhat the same way at first with the keys, but it's deceptive. Let's say you break a pot, a key appears and then you walk away.
You need to track each key that can be missed and then you might as well track them all. Doors are somewhat simular in that you are working in pairs. Saving that data on the area level saves you some headache as well.
Looking over your explination I'm starting to warm up to your idea, but there are the few issues I mentioned. It is then important that we are both in agreement on how the data needs to be saved. Like a uniform template. We wouldn't want your data to look like A and mine like B.
A.
dungeon[x,0] -> number of keys still available to Link
dungeon[x,1] -> temporary status indications that only last as long as Link visits this room cluster.
dungeon[x,2]-[x,4] -> the permanent status of the dungeon.
B.
dungeon[x,0] -> number of keys still available to Link
dungeon[x,1] -> the permanent status of the dungeon.
dungeon[x,2] -> tracks broken walls
dungeon[x,3]-[x,4] -> temporary status indications that only last as long as Link visits this room cluster.