Elite's Thread of Questions

I have a quick question involving functions and multiple strings.

Say, I have a simple functions like this one.
Code:
int function(string itemname) {
item x = to_item(itemname);
int y = mall_price(x);
return y;
}

And I also have a list of item names like:
("item1", "item2", etc)

What is a good way to get the function to enact on each of these items without going like
Code:
function("item1")
function("item2")
etc..

I will probably be posting a lot longer post here in the next day or two when I have a little more free time and thanks for all the help so far.
 

Bale

Minion
What is a good way to get the function to enact on each of these items without going like
Code:
function("item1")
function("item2")
etc..

Code:
int func(string itemname) {
   item x = to_item(itemname);
   int y = mall_price(x);
   return y;
}

foreach it in $strings[item1, item2]
   print("Price of "+ it +" is: "+ func(it));

Note that you do not use double-quotes inside the $strings[] delimiter unless they are part of the string. If you need to use a comma as part of a string, make sure you escape it with a back-slash. You can also do...


Code:
int func(item x) {
   int y = mall_price(x);
   return y;
}

foreach it in $items[item1, item2]
   print("Price of "+ it +" is: "+ func(it));

All constants can be grouped that way.
 
Last edited:
Alright, so I think I am doing something wrong because it isn't working for me.

My first question is could I do something like
Code:
string x = $strings[cat, dog]

foreach it in x
    print(" "+ it +" ,");

I tried that and it was saying something about "Aggregate reference expected" so I am assuming that is a no.

Anyways, doing how you had it works perfectly and for that I thank you good sir.
 
Thanks lost, that worked perfectly; however, I do not fully understand why it worked. If someone could explain it to me or point me in the direction where I could read about it more I'd really appreciate it.

Next, I was wondering how I would append more strings to the container, in this case x.

Say I have
Code:
boolean[string] x = $strings[cat, dog]
I then check to see if I have a goat and if I do I add it to the list so I get
Code:
 x = $strings[cat, dog, goat]
 
This page, http://wiki.kolmafia.us/index.php?title=Data_Structures, and its links are a good place to start to get into how maps of different data types work.

Yeah I reference that page a lot. I guess the main problem is I am unfamiliar with maps and keys. The first few times I looked at that web page I couldn't figure out why it was talking about maps and keys when KoL didn't really have maps or keys lol. It was about a week later that I realized it wasn't actually talking about "maps" and "keys" as items but rather as a concept.

As for the code, I tried
Code:
 boolean[string] x = $strings[cat, dog];
x["goat"] = true;
foreach it in x	
    print(""+ it +"");

It gave me a "Cannot modify constant value" error. So I tried
Code:
boolean[string] x;

x["cat"] = true;
x["goat"] = true;
foreach it in x	
    print(""+ it +"");

Which worked, but not quite what I wanted. I can make due with it tho.
 
Last edited:

Winterbay

Active member
Yeah, they are still the thing with ash-programming I have the most problem wrapping my head around, especially when it gets to multidimensional maps...
I tend to use string[int]-maps a lot since I find those to be the easiest to get into my head since they are basically a numbered list of things.
One way of getting to understand what you have is to do a map_to_file() on your map in order to see how the data is represented in a more visual way.
 
Alright, thanks Winerbay. I tried messing around with the map_to_file() before but I think I made my map incorrectly so it was just giving me an error. I think the biggest problem I have is what the criteria is for designating an object a map vs a key. After that, it is figuring out what to use them for, but I think I will put that off for now x).
 
New questions. I am trying to write a script that will tell me all I have gotten from farming a location. I got a semi working script at the moment thanks to the tricktreat script. It looks like this currently.
Code:
for i from 0 to 5 {
	advstring = visit_url("adventure.php?snarfblat=324");
	if (advstring.contains_text("You're fighting")) {
		advstring = run_combat();
		loot = extract_items(advstring);
	}
	foreach c in loot
	totalloot[c.to_string()] += loot[c];
}

It works great until I hit a choice combat. Is there a good way of handling those? I.e. a simple command like run_combat()? Or do I have to manually code in the choice adventures? Or is there an even better way of accomplishing what I am trying to do?

Also, on a side note, what do the syntax of the periods mean? I.e. if (advstring.contains_text). I see them around a lot but have no clue what they are doing.
 

Bale

Minion
The simple command for handling a choice is cli_execute( "choice-goal" );

I'm not sure that is the best way of handling the matter though. If you are not in a combat, run_combat() will tell you the results of the last combat. So, if you adventure(1, loc) then you can use extract_items(run_combat()) to determine the items you got in the combat that was already handled by adventure().

If get_property("lastEncounter").to_monster() != $monster[none] you will know that the last adventure was a combat.
 

Theraze

Active member
Also, on a side note, what do the syntax of the periods mean? I.e. if (advstring.contains_text). I see them around a lot but have no clue what they are doing.

The periods are an alternate way of accomplishing a function call. So c.to_string() is the same as to_string(c) just written a bit differently. And advstring.contains_text("You're fighting") is the same as contains_text(advstring, "You're fighting") just... you get the idea. :) Which is better? It generally comes down to personal preference. You could probably have done loot = advstring.extract_items() if you really wanted to. :)
 

fronobulax

Developer
Staff member
I wanted to keep track of everything that I had after adventuring. Since I only cared about what happened between login and logout, what worked most reliably was to have a script that generated what was in my inventory (and closet and equipped) at login, write it to a file and then read the file and compare it to what was in those places at the end. That turned out to be easier than monitoring adventures. Just an observation.
 

Theraze

Active member
Alternatively, you can do something like this alias:
trackitems => ashq int [item] currentinv = get_inventory(); int currentmeat = my_meat(); try{cli_execute("%%");}finally{ int [item] postinv = get_inventory(); int postmeat = my_meat(); foreach i2,c2 in postinv{if (postinv[i2] != currentinv[i2]) print(i2 + ": " + (postinv[i2].to_int() - currentinv[i2].to_int()));} foreach i1,c1 in currentinv{if (postinv[i1] == 0) print(i1 + ": " + (-c1));}if (postmeat != currentmeat) print("Meat: " + (postmeat - currentmeat));}

What this does is compares the difference in both your items and meat between when you first run the alias and when it finishes. It's designed so that you can run whatever else inside it... trackitems tricktreat, for example, would run the tricktreat script and then tell you the total difference for both items and meat overall. It runs in a try/finally so that it's harder not to get the summary... the first time you abort it should be aborting the script or adventuring, while if you keep mashing the abort button it will finally quit without the summary. But hey, improved chances.

I run it sometimes when I want to know exactly how much a specific farming script is gaining or costing me. :)

Edit: Using the trackitems alias, your 5 adventure in the castle top would be:
trackitems adventure 5 castle top
 
Last edited:
That sounds exactly what I am looking for Theraze, and it comes with the functionality of working with other things. However, what is an alias? Would I put that in a script file and then when I want to track the items/meat just call it and then the script I want to run?
 

Theraze

Active member
To define an alias, you do the alias name followed by => and then what you want it to do. So to define the trackitems alias, you'd copy-paste:
alias trackitems => ashq int [item] currentinv = get_inventory(); int currentmeat = my_meat(); try{cli_execute("%%");}finally{ int [item] postinv = get_inventory(); int postmeat = my_meat(); foreach i2,c2 in postinv{if (postinv[i2] != currentinv[i2]) print(i2 + ": " + (postinv[i2].to_int() - currentinv[i2].to_int()));} foreach i1,c1 in currentinv{if (postinv[i1] == 0) print(i1 + ": " + (-c1));}if (postmeat != currentmeat) print("Meat: " + (postmeat - currentmeat));}
To use it, you'd just start whatever command in the gCLI with the alias. Example:
> trackitems buy 1 toy accordion

Searching for "toy accordion"...
Search complete.
Purchasing toy accordion (1 @ 150)...
You acquire an item: toy accordion
You spent 150 Meat
Purchases complete.
toy accordion: 1
Meat: -150
Note that aliases are a little bit tricky and will actually fire wherever in the line they're run, so if you try to name an alias something like item, you will no longer be able to maximize item, because you'll be maximizing <whatever your item alias is> and so on. Just try to keep your alias names descriptive enough that you know what they are, short enough that they aren't a pain to type, and unique enough that they aren't going to conflict with normal typing, chatting, or internal mafia bits. :)
 
Alright, it to works great :D. Thanks a lot Theraze! Mind answering a few questions on it?

I see that the first half is just saving before/after inv and meat and executing the command. The second part is analyzing the inventory. If I understand it correctly...
Code:
 foreach i2,c2 in postinv{if (postinv[i2] != currentinv[i2]) print(i2 + ": " + (postinv[i2].to_int() - currentinv[i2].to_int()));}
This part is looking at each item (i2) and comparing it to past inventory. If it is different it prints out the item and the amount it differs by.

Then the second part
Code:
 foreach i1,c1 in currentinv{if (postinv[i1] == 0) print(i1 + ": " + (-c1));}
is printing the items that you lost and how many were lost, all relative to your past inventory.

What is the reason behind using i1,c1 for the 2nd part and i2,c2 in the first? Is it just notation or do they mean something more? Could you have just used i,c for everything?

Lastly, is there a location aliases are stored that I could go change them? Or do I have to just unalias it and then re-alias it with the new code? I was thinking about adding it to export the information into a file that I could then read in by another script to do cost analyses (or maybe even just do that within the alias itself).
 

Theraze

Active member
I probably just moved the ordering between the two, preferring to see items gained over items lost. :)

And yes, I could have used the same for everything, but if I wanted to make the items iterate over each other, I need to do something that won't conflict. I needed to iterate through each though, because I preferred to only iterate over the actual inventories rather than the full item list. :)

You can find all of your aliases in the GLOBAL_aliases.txt file in your settings folder. Note that like any file in the settings folder, you can only change items in it while it's not actively loaded into mafia. As this is a GLOBAL file, that means all of your mafia sessions need to be closed to manually edit it. Also, before editing, make sure that you have a backup... if you happen to use a bad text editor, it can mess with the line breaks or encoding in a way that makes it no longer load for mafia, so it's easier to just be able to copy your working file back after you've renamed your broken updated file so that you don't lose those changes.
 

lostcalpolydude

Developer
Staff member
If you don't want to rename an alias, you can just make another alias with the same name to replace the old one. You can use "alias" by itself to see all of your aliases.
 
Top