Maps for dummies

Asinine

New member
Hi.

First off: I'm trying to expand my knowledge of maps. I have very limited experience with C and C++ from a while back (I passed intro to computer programming/C++ in jr. college with a C seven years ago), but this ASH stuff doesn't seem too difficult. I've found a number of already-written ash files that would do what I want to do (with personal tweaking), but my goal is to create the basic file myself. That, and no matter how hard I tried to pick them apart, I wasn't ever completely successful to get the file to do exactly what I wanted. :)

So, all that being said, this is what I am trying to do:
I want to make an inventory clean up script. I have a text file for the map with the number of items I want to keep, the item name, and what I want to do with it, all separated with a tab like this:
Code:
0	Arrrmetia trading card	mallsell
1	asbestos apron	pulv
1	asbestos crossbow	autosell
I want to sell all Arrrmetia cards in the mall, pulverize all but one of my aprons, and sell all but one crossbow.

Now, the problem is this: maps hate me. Or better put, my brain hates maps. I know the vague idea behind maps, but I've never understood them. I know that once I pull out the various values for each line, I have the capacity of writing the code to dispose of the item properly. I just don't get the maps... :confused:

Now, I'm thinking of having the code do something like this:
Code:
if (value3 of map[1] == "mallsell")
	mallsellfunc(int value1, item value2);
where value1 and value2 are the first two parts of that map thingy.
Sorry, my terminology sucks :D

I could rewrite all this stuff with cli_executes and whatnot, but I really want to learn maps, and I've already created the humongous file of crap I want to deal with. If there is a simple way to explain this, I would be most grateful. I'm hoping it's just a simple deal with learning the commands to pull the various values out of the map... Hopefully.

Thanks in advance.
 

jasonharper

Developer
The text file you have isn't very suitable for use as a map. Every entry has to have a distinct key or keys, which are always the leftmost fields in the file. However, your first field isn't unique, and therefore cannot be the key (if you tried to use it that way, the 3rd line in your example data would overwrite the 2nd, since they have the same key). You have two basic choices here:

1. Since you do have a field which should be unique over the entire map (the item name), the ideal solution would be to move that field to the left, and use it as the key. The values of your map would have to be records, consisting of an int field (the number to keep) and a string field (the action). The declaration of the map would look like:
Code:
record myRec {
  int keep;
  string action;
};
myRec[item] myMap;
And the code to iterate over the map would be:
Code:
foreach itm in myMap {
  int toKeep = myMap[itm].keep;
  string theAction = myMap[itm].action;
  // do something with this entry...
}

2. If you can't stand the thought of having to rearrange the fields in your existing file (although that shouldn't take more than 30 seconds with a decent text editor), your only choice would be to have a map with multiple keys, so that together they uniquely identify each entry. This would require two keys in your case (int and item), with a string value (the action). Note that it will be impossible to look up data in such a map, since you would have to provide both an int and and item as keys, and you wouldn't know what combinations are valid unless you'd already looked up that data in the map! However, for your purposes you wouldn't ever need to look up an individual entry, you'd only be iterating over all the entries. The declaration of the map would look like:
Code:
string[int, item] myMap;
And the code to iterate over the map would be:
Code:
foreach toKeep, itm in myMap {
  string theAction = myMap[toKeep, itm];
  // do something with this entry...
}
 

Asinine

New member
your first field isn't unique, and therefore cannot be the key

Oooh, that almost makes sense! :D Thanks for the quick response; I'm going to fiddle around with this later and see if it works out tomorrow.
 

Asinine

New member
Alrighty. Time has been a bit churlish so I'm just now gonna try to explain what I'm missing.

My first issue I've run into is that I'm not equating how to include my text file (I was assuming it'd be with a file_to_map()), and how to incorporate the "record myRec" and "myRec [item] myMap" around it. Actually, I don't get that record/myRec bit at all.

I'm guessing that
Code:
record myRec {
  string action;
  int keep;
}
somehow takes my theoretically-previously-injected text file and divvies up the last two values, presumably as the two values attached to each map key (each key being the item name). (By the way, I swapped my second and third values; jasonharper put the numerical values into the second slot, I moved them to the end/third instead.)

If I'm following that correctly, I'm still completely lost as to how myRec becomes a function (of sorts?) that can now handle some variable "item" (I'm not sure if I'm supposed to insert the map key/item name there, or if that's an ingrained variable/command/something) and make a new... function? variable? map? string? called "myMap".
I see that below it seems to be a string of sorts, because there's a for i = statement immediately following, which then is where I put what to do with each item.

Or, I just realised that maybe record is a static type? Gah, now I'm really confused. But maybe it makes more sense. That would allow "myRec[item] myMap;" to make a little more sense... but I dunno. I need sleep, and I know it's not gonna click until I'm more awake.

I probably won't be able to touch this for another few days, but any help is still greatly appreciated.
 

jasonharper

Developer
"record" defines a new data type (named "myRec" in the example), containing a fixed number of other data types (a string and an int, in this case), which can then be manipulated as a single unit. The representation of a record, inside of a file used via file_to_map(), consists of the individual elements separated by tabs.

I left out the actual call to file_to_map() in my examples, because that didn't seem to be the part you were having trouble understanding. The call can go anywhere after the actual declaration of the map (so that it knows how to interpret the data in the file), but before the usage of the map data.
 

Bale

Minion
If I may, here is a short example of how to use records and maps:

Code:
record myRec {
  string action;
  int keep;
}
myRec[item] MyItems;

MyItems[Arrrmetia trading card].action = "mallsell";
MyItems[Arrrmetia trading card].keep = 0;
MyItems[asbestos apron].action = "pulverize";
MyItems[asbestos apron].keep = 1;
MyItems[asbestos crossbow].action = "autosell";
MyItems[asbestos crossbow].keep = 1;

map_to_file(myMap, "item_list.txt");

Will create a file that looks like this:
Code:
Arrrmetia trading card	mallsell	0
asbestos apron	pulverize	1
asbestos crossbow	autosell	1

Obviously you could have created that file using a text editor instead of a script, but this does give you a sense for how to assign data in a record. Then in another script you can do something like this:

Code:
record myRec {
  string action;
  int keep;
}
myRec[item] MyItems;
file_to_map("item_list.txt", MyItems);
foreach key in myItems
	if(myItems[key].keep < item_amount(key))
		cli_execute(myItems[key].action + " "+ to_string(item_amount(key) - myItems[key].keep)+ " "+ key);

Okay, I probably wrote more of that script than I should have, but it was so short... Anyway, this example should be enough for you to figure out anything else you'd want to know on the subject.
 
Last edited:

Asinine

New member
Thank you both for the help. I was hoping to figure it out without a whole example (I really don't want to leech without learning :), but I do appreciate the time you took to make it.

I think I will be okay with what you've both said.

Thanks again!
 

Asinine

New member
I'm back. Sorry.

I had two maps going, and I kept getting an error with the one I made up on my own. I thought that maybe the error I was getting was all about PEBCAK. But then I eliminated it, and sadly, it's not just my code. It was simply because my code was before the one I used from you guys.

I get the error "Expected ;, found [" on the line
Code:
  myRec[item] myMap;

From both of your examples, there are no commas in this line, and I'm lost to as why I get this error.
 

Asinine

New member
Yeah, I checked that.

The function is as follows:
Code:
void main() {
  record myRec {
    string action;
    int keep;
  }

  myRec[item] myMap;

Like I mentioned, I had created another map before (it was so I could track errors or failures for the commands I wanted to execute), and it was popping up with this exact error. So I just removed the "error checking feature" (aka my new mapping) by commenting everything else, and it skipped down to this line. I commented out the entire contents of main(), then it "works"... just that it then doesn't do anything, naturally.
 
Last edited:

Alhifar

Member
Code:
record myRec {
    string action;
    int keep;
  }
should be:
Code:
record myRec {
    string action;
    int keep;
  };

Records need a semi-colon after the ending brace.
 

Alhifar

Member
Add the semi-colons after the record curly braces, and I'd recommend replacing your "ProblemMap[item] Issues" with simply "string[item] Issues"
 
Top