Can't figure out this error with records in maps...

Paragon

Member
I am having a strange problem. Whenever I attempt to use a record in a map at the end of the script the map only contains the data from the last record...
I.E:
This psuedo code (when implemented) always fills all records in the map with the contents of the last assignment.
Code:
Record aRec
{
   string always_the_same;
};

aRec[string] aMap;

aRec temp_Record;

 <Populate aRec>
 aMap["one"] = aRec;

 <Clear and repopulate aRec>
 aMap["two"] = aRec;

 <Clear and repopulate aRec>
 aMap["three"] = aRec;
  
 foreach key in aMap
 {
    <print aMap[key] contents>
 }

To explain a little better, if I assign aRec.always_the_same with any three Diffrent values the last for each loop will always only print the value of the last aRec assignment. It will associate the same value with all three keys.

Here is the entire code: (Hint: Search for #****PROBLEM***# to find it easily)
Oh, and sorry bout the mess.... Thank you in advance to anyone willing to help out.
Code:
string getmodsFile = "modifiers.txt";     #Where to find the data for modifiers
string getoutfitsFile = "outfits.txt";     #Where to find the data for outfits
string equipmentDataFile = "c_equip.txt"; #Where to put new modifier map file
string outfitDataFile = "c_outfit.txt";   #Where to put new outfit map file


Record modRec
{
  string item_mod;
};

Record outfitDataRec
{
  item hat;
  item pants;
  item shirt;
  item weapon;
  item offhand;
  item acc1;
  item acc2;
  item acc3;
  string mod;
};

#modRec [string] tempItemModMap;
string [slot, item] itemModMap;
outfitDataRec[string] outfitModMap;

void execute()
{
}

#string lookup_effect(

void print_ODRecord(outfitDataRec i)
{
  print ("__________");
  print ("Hat: "+to_string(i.hat)); 
  print ("Shirt: "+to_string(i.shirt)); 
  print ("Pants: "+to_string(i.Pants)); 
  print ("Weapon: "+to_string(i.weapon)); 
  print ("OffHand: "+to_string(i.offhand)); 
  print ("ACC1: "+to_string(i.Acc1)); 
  print ("Acc2: "+to_string(i.acc2)); 
  print ("Acc3: "+to_string(i.acc3)); 
  print ("Mod: "+i.mod);
  print ("__________");
}

void install()
{
  slot item_slot;  #Slot for mapping items
  item item_item;  #item for mapping items
  item [int] tIE; # temp Intrinsic Effect map to replace all instances of intrinsic effects
                    # with their actual modifier.
  string [string] tEffectMap; # map of effect modifiers keyed by effect name.
  int c=0;         #a counter
  string sString;

  modRec [string] tempItemModMap;
  #string [string] tempItemModMap;

#  modRec [string, string] tempOutfitMap; #used to read the outfits.txt
  string [int, string] tempOutfitMap; #used to read the outfits.txt

  if (!(file_to_map(getmodsFile, tempItemModMap)))
  {
    cli_execute("Abort Modifiers.txt could not be loaded.");
  }

  if (!(file_to_map(getoutfitsFile, tempOutfitMap)))
  {
    cli_execute("Abort outfits.txt could not be loaded.");
  }

  #Load outfits into the new format.
  int AccCount = 0;
  string [int] parts;
  outfitDataRec tODRec;
  slot tSlot;
  item nullItem = to_item("");
  foreach i in tempOutfitMap
  {
    string[string] ii = tempOutfitMap[i];
    AccCount=0;
    foreach s in ii
    {
      tODRec.hat=nullItem;
      tODRec.pants = nullItem;
      tODRec.shirt = nullItem;
      tODRec.weapon = nullItem;
      tODRec.offhand = nullItem;
      tODRec.Acc1 = nullItem;
      tODRec.Acc2 = nullItem;
      tODRec.Acc3 = nullItem;
      tODRec.mod="NONE";

      parts = split_string(tempOutfitMap[i,s],",");
      foreach p in parts
      {
         tSlot = to_slot(to_item(parts[p]));
         if (tSlot==$slot[Hat]){tODRec.hat = to_item(parts[p]);}
         if (tSlot==$slot[Pants]){tODRec.pants = to_item(parts[p]);}
         if (tSlot==$slot[Shirt]){tODRec.shirt = to_item(parts[p]);}
         if (tSlot==$slot[Weapon]){tODRec.weapon = to_item(parts[p]);}
         if (tSlot==$slot[Off-hand]){tODRec.offhand = to_item(parts[p]);}
         if (tSlot==$slot[Acc1]){
           if (AccCount==0){tODRec.acc1 = to_item(parts[p]);}
           if (AccCount==1){tODRec.acc2 = to_item(parts[p]);}
           if (AccCount==2){tODRec.acc3 = to_item(parts[p]);}
           AccCount = AccCount+1;
 
         }
#         print (parts[p]+"::"+to_string(to_slot(to_item(parts[p]))));
          
      }
       #****PROBLEM***#
       #****Obviously this ISN'T where the problem originates, but it is where the problem can most
       #****easily be observed.
        print (s);
	print_ODRecord(tODRec);
        outfitModMap[s]=tODRec;
        print_ODRecord(outfitModMap[s]);
    }
#    print (tempOutfitMap[i]);
#    print (i);
	
  }

  map_to_file(outfitModMap,"DebugFile");
  #load all the effects into the map.
  boolean done = false;
  foreach i in tempItemModMap
  {
     if (to_string(to_slot(to_item(i))) != "NONE") #Make sure it is an equipable item and not an outfit, skill, etc.
     {
       if (tempItemModMap[i].item_mod != "NONE")  #Make sure it has an effect
       {
         item_slot = to_slot(to_item(i));
         item_item = to_item(i);
         itemModMap[item_slot, item_item] = tempItemModMap[i].item_mod;
         if (index_of(tempItemModMap[i].item_mod, "Intrinsic") >= 0) 
         #This item has an intresic effect so put it on the list to be fixed later
         {
	   tIE[c] = to_item(i);
           c=c+1;
         }
       }
     } else {
     #It is not an equipable item, but it may be an intrinsic effect, or an Outfit effect

       done = false;
       foreach s in outfitModMap
       {
         #print (s);
         #print (i);
         if (s==i)
         {
           #outfitModMap[s].mod = tempItemModMap[i].item_mod;
#           Print ("MATCH-----------------"+s+"::"+i);
           done = true;
           break;
         }
        
       }     
       if (!done) {tEffectMap[i]=tempItemModMap[i].item_mod;} #Store it for later use as an intrinsic effect
     }
  }
  
 foreach s in outfitModMap
 {
#   print_ODRecord(outfitModMap[s]);
 }

 #Replace Intrinsic effects with their actual effect.
  foreach effect in tEffectMap
  {
     foreach item in tIE
     {
       if(index_of(itemModMap[to_slot(tIE[item]), tIE[item]], effect) >=0)
       {
          print(itemModMap[to_slot(tIE[item]),tIE[item]] + "::" +effect+ "::" + tEffectMap[effect]);
          sString = "Intrinsic Effect: \""+effect+"\"";
          itemModMap[to_slot(tIE[item]),tIE[item]]=replace_string(itemModMap[to_slot(tIE[item]),tIE[item]],sString ,tEffectMap[effect]);
#          print (itemModMap[to_slot(tIE[item]),tIE[item]]);
       }
     }
  }
  
  map_to_file(itemModMap,equipmentDataFile);
  print ("Installation complete.");
}

void main() 
{
 # if (!(file_to_map(equipmentDataFile, itemModMap)))
 # {
    install();
 # }
  execute();
  
}
 

Paragon

Member
Ok, so I was still tring to fix it, and in the proccess of fixing it, i *think* I may have discovered a bug... either that or I am confused about something. Anyway, I want to run it by the more experienced scripters before I file any kind of bug report.

I have replecated the proposed bug as concisly as I could in the following code.
Code:
void main()
{
    Record aRecord{
          int var1;
          string var2;
    };

    aRecord [string] aRecordMap;
    aRecord temp_record;

    temp_record.var1 = 1;
    temp_record.var2 = "2";
    aRecordMap["foo"] = temp_record;
    temp_record.var1 = 3;
    temp_record.var2 = "4";
    aRecordMap["Bar"] = temp_record;

    foreach key in aRecordMap
    {
       print (key);
       print (aRecordMap[key].var1);
       print (aRecordMap[key].var2);
    }
}

I would think that the expected output of that program would be:
1 -or even possibly - 3
2 4
3 1
4 2

The outcome I was experienceing was:
3
4
3
4

Finally, I removed the temporary record variable (it was only their to make the code more readable) and made the assiments directly to the records in the map. The output worked as predicted "unbugged".
Code:
void main()
{
    Record aRecord{
          int var1;
          string var2;
    };

    aRecord [string] aRecordMap;

    aRecordMap["foo"].var1 = 1;
    aRecordMap["foo"].var2 = "2";
    aRecordMap["Bar"].var1 = 3;
    aRecordMap["Bar"].var2 = "4";

    foreach key in aRecordMap
    {
       print (key);
       print (aRecordMap[key].var1);
       print (aRecordMap[key].var2);
    }
}
 

hippymon

Member
As for help with your first post:
Please attach a copy of all the data maps included in this script so we know what we have to work with. I came up with a functioning version, but I don't know if it is how you desire it to function, I have attached it.

And for the second post:
You get
The outcome I was experienceing was:
3
4
3
4
Because mafia does not know that you wish for these to sets of data to be together:
Code:
	temp_record.var1 = 1;
	temp_record.var2 = "2";
	aRecordMap["foo"] = temp_record;
Code:
	temp_record.var1 = 3;
	temp_record.var2 = "4";
	aRecordMap["Bar"] = temp_record;

Code:
Record aRecord{
	int var1;
	string var2;
};
void main(){
	aRecord [string] aRecordMap;
	aRecord temp_record;
	temp_record.var1 = 1;
	temp_record.var2 = "2";
	aRecordMap["foo"] = temp_record;
#### NOTICE ####
	print("1: " + temp_record);
#### /NOTICE ####
	temp_record.var1 = 3;
	temp_record.var2 = "4";
	aRecordMap["Bar"] = temp_record;
#### NOTICE ####
	print("2: " + temp_record);
#### /NOTICE ####
	foreach key in aRecordMap{
		print (key);
		print (aRecordMap[key].var1);
		print (aRecordMap[key].var2);
	}
}
Note the "print()'s" I added, it come up with:
1: record aRecord
2: record aRecord


To make this function like I believe you want it to I would use the following code:
Code:
Record aRecord{
	int var1;
	string var2;
};
void main(){
	aRecord [string] temp_record;
	temp_record["foo"].var1 = 1;
	temp_record["foo"].var2 = "2";
	temp_record["Bar"].var1 = 3;
	temp_record["Bar"].var2 = "4";
	foreach key in temp_record{
		print("key = " + key, "red");
		print("temp record var1 = " + temp_record[key].var1, "blue");
		print("temp record var2 = " + temp_record[key].var2, "blue");
	}
}
Notice we rid the use of "aRecordMap"
Instead we changed
aRecord temp_record
To:
aRecord [string] temp_record
 

Veracity

Developer
Staff member
[quote author=Paragon link=topic=1406.msg6468#msg6468 date=1198832299]
Anyway, I want to run it by the more experienced scripters before I file any kind of bug report.[/quote]
Should I wait until you file a bug report before I explain that it's not a bug? :)

Code:
Record aRecord{
      int var1;
      string var2;
};

aRecord [string] aRecordMap;

aRecord temp_record;
temp_record.var1 = 1;
temp_record.var2 = "2";

aRecordMap["foo"] = temp_record;
You created a single record - temp_record - and filled it in.
You then made an entry in your map such that "foo" maps to that record.

Code:
temp_record.var1 = 3;
temp_record.var2 = "4";
aRecordMap["Bar"] = temp_record;
You modified your single record - and if you fetch it from the map, you will see that you modified the same record - and store it again in your map. Your map now has two mappings pointing to the same record.

What you seem to not understand is this: when you store something into a map, ASH does not copy it. It stores the precise object that is on the right side of the equals sign. And if it's an aggregate - a record or a map - you can modify that precise object, just as you are observing.

Your program wants distinct records for each map reference. There are several ways to do this.
Here is one way:

Code:
record aRecord {
      int var1;
      string var2;
};

aRecord new_rec( int v1, string v2 )
{
    aRecord temp;
    temp.var1 = v1;
    temp.var2 = v2;
    return temp;
}

aRecord [string] aRecordMap;
aRecordMap["foo"] = new_rec( 1, "2" );
aRecordMap["Bar"] = new_rec( 3, "4" );

Here is another way:

Code:
record aRecord {
      int var1;
      string var2;
};

aRecord new_rec()
{
    aRecord temp;
    return temp;
}

aRecord [string] aRecordMap;
aRecord temp_rec;

temp_rec = new_rec();
temp_rec.var1 = 1;
temp_rec.var2 = "2";

aRecordMap["foo"] = temp_rec;
temp_rec = new_rec();
temp_rec.var1 = 3;
temp_rec.var2 = "4";
aRecordMap["Bar"] = temp_rec;
Take your pick.

...which said, it probably wouldn't be a bad idea if instead of:

Code:
aRecord new_rec()
{
    aRecord temp;
    return temp;
}

aRecord temp_rec = new_rec();
you could simply use:

Code:
aRecord temp_rec = new aRecord;
I'll add it to my to-do list.
 
Top