PDA

View Full Version : acquireBuff - Get a buff from a buffbot



Rinn
04-25-2010, 10:41 PM
AcquireBuff 1.6

[requires zlib (http://kolmafia.us/showthread.php?t=2072)]
[visits external servers]

You cannot modify a setting by changing the value in script, instead type the following into the cli (change acquireBuff_max_price to the setting you wish to edit):

zlib acquireBuff_max_price = 1000This script will attempt to get you a buff from a buffbot without needing to know the price or even the bot's name. It will only attempt to send meat to each buffbot once, if they're online, and if the price of the buff is less then your 'acquireBuff_max_price'. Once a buff is requested at a certain price it will not request using that price again. Philanthropic buffs are never considered. AT buffs are no longer requested if you're can't listen to any more songs.

Future Improvements:

Removing buff packs from consideration, maybe
Fun fact: I accidentally spent 100k on empathy while writing this script and now I have 60k turns remaining.

1.6 Fix a boolean function not returning true, which would break the script in a future mafia update.
1.5 Move "Four Songs" check out of the top level so it will get resolved every run instead of just once.
1.4 Slyz Fixes
1.3 Checks if you can't acquire an at buff due to song count before requesting it
1.2 Rename jingle bells to jingle jangle jingle, maybe something else idk
1.1 Allow requesting a buff you already have
1.0 Initial Release

slyz
04-26-2010, 07:07 AM
Thanks Rinn!

I haven't tried it out yet, but I know I generally request buffs from buffbots even when I already have turns of the effect running. Maybe you could add a variable that can be used in the while loop


original_num_turns = have_effect(e);
while(have_effect(e) == original_num_turns)
...


And a small advice: on top on being able to control verbosity, vprint() was also designed to save typing in a situation when you want to return a boolean value and print a message, so you could replace


if (!try_acquire_buff(e))
{
vprint("Unable to acquire " + e.to_string(), "red", 2);
return false;
}

by


if (!try_acquire_buff(e))
return vprint("Unable to acquire " + e.to_string(), -2);

(notice the 2 became negative, to return false, so the string will be printed in red).

oly0015
06-16-2010, 09:58 PM
"Future Improvements:
AT song count checking"

If it helps, for the script i'm working on when I wanted to check the song count I made a list of the known songs in an array and ran through them with a foreach. Then all you have to do is use a if statement with have_effect(array item) > 0 to see if that song is active. At that point just use an index variable to count this and at the end do an equip check for song total adding items such as the pendant.

Handy script, I actually imported it for mine, when I get done with mine you might be interested in how i used your script.

heeheehee
06-16-2010, 10:25 PM
You don't actually need an equip check, as the song modifiers (additional song and 4 songs) are both boolean modifiers (http://wiki.kolmafia.us/index.php?title=Modifiers#Boolean_Modifiers).

Bale
06-16-2010, 10:35 PM
As heeheehee said. This is what you need to know:


boolean four_songs = boolean_modifier("four songs");
boolean extra_song = boolean_modifier("additional song");
int max_songs = 3 + to_int(four_songs) + to_int(extra_song);
print("You can currently hold "+ max_songs +" songs in your head at a time.");

oly0015
06-16-2010, 10:38 PM
should save me a couple lines, guess i got to go fix stuff, ty

Bale
06-16-2010, 10:41 PM
Oh. And this:


int current_songs() {
int total = 0;
for skill_num from 6001 to 6040
if(skill_num.to_skill() != $skill[none] && skill_num != 6025 && skill_num.to_effect().have_effect() > 0)
total = total + 1;
return total;
}

oly0015
06-17-2010, 07:06 AM
might be just because its late, but i tried acquireBuff($effect[buff]); where buff = "ode to booze" and got
No known buffbot is able to provide Surreally Buff
Unable to acquire Surreally Buff

time for some sleep then i guess i'll figure it out later

Winterbay
06-17-2010, 08:05 AM
It is possible the problem is the naming. The buff is called "the ode to booze". Please bear in mind that I have no idea and have not looked at the code :)

lostcalpolydude
06-17-2010, 09:47 AM
The skill is called The Ode to Booze, but the effect is called Ode to Booze, so the latter is what you want. It looks like you're passing "buff" to the function rather than "ode to booze", so it looks for a buff with "buff" in the name. If

acquireBuff($effect[buff]); where buff = "ode to booze"
is what you typed in, then that won't work, just use

acquireBuff($effect[ode to booze])
instead.

slyz
06-17-2010, 02:11 PM
If lost is right, and you had a string variable buff, that contained "ode to booze", then you should do:


acquireBuff( buff.to_effect() );

oly0015
06-17-2010, 04:19 PM
Yep, seems i can't cheat to use $effect[] instead of the proper conversions. Anyway this works for now, i'm correcting my code still from last night for the other half atm.


void getbuff (string buff)
{
if (have_skill( to_skill( buff )))
{
if ((mp_cost( to_skill( buff ) )+1) < my_mp() )
{
use_skill( 1, to_skill( buff ));
}
else
{
mp_heal(mp_cost( to_skill( buff ) )+1);
use_skill( 1, to_skill( buff ));
}
}
else
{
print ("Buying you some "+buff,"green");
acquireBuff(to_effect( buff ));
}
}

slyz
06-17-2010, 05:02 PM
I think there are skills and effects that don't share the same name, so using to_skill() and to_effect() to the same string might not work in every case.

You should pass in an effect:


boolean getbuff (effect buff)
{
if ( have_skill(to_skill( buff )) )
{
if ( (mp_cost( to_skill( buff ) )+1) > my_mp() )
mp_heal(mp_cost( to_skill( buff ) )+1);
return use_skill( 1, to_skill( buff ));
}
else
{
print ("Buying you some "+buff,"green");
return acquireBuff(buff);
}
}

Of course, you could also input a skill, and use have_skill(buff) and acquireBuff(buff.to_effect()).
Oh, I also changed the return value to a boolean, since Rinn already returns a boolean from acquireBuff().

EDIT: Another small thing: in most cases, buffbots have access to really cheap MP, so generally it will be cheaper to buy a buff from a buffbot rather than cast it on yourself. Although I guess that when you only want a single shot of Ode, for example, it's not really worth waiting for a bot to buff you.

oly0015
06-17-2010, 05:08 PM
Yep, I've got it set for now to use rinns script straight through, unless its ode

slyz
06-17-2010, 05:23 PM
Oh. And this:


int current_songs() {
int total = 0;
for skill_num from 6001 to 6040
if(skill_num.to_skill() != $skill[none] && skill_num != 6025 && skill_num.to_effect().have_effect() > 0)
total = total + 1;
return total;
}

There's a to_skill() missing there:

int current_songs() {
int total = 0;
for skill_num from 6001 to 6040
if(skill_num.to_skill() != $skill[none] && skill_num != 6025 && skill_num.to_skill().to_effect().have_effect() > 0)
total = total + 1;
return total;
}

EDIT: Rinn - sorry for the huge threadjack!

oly0015
06-17-2010, 05:30 PM
Oh if it helps for bales code, i had to make a bit of an edit, in his math the hookah buff if its an AT song doesn't get counted. What this does is if the hookah goes beyond your maximum amount of songs this code will take off the song it buffed.



boolean four_songs = boolean_modifier("four songs");
boolean extra_song = boolean_modifier("additional song");
int max_songs = 3 + to_int(four_songs) + to_int(extra_song);


int total = 0;
for skill_num from 6001 to 6040
{
if(((skill_num.to_skill() != $skill[none]) && (skill_num != 6025)) && (have_effect(to_effect(to_skill(skill_num))) > 0))
{
total += 1;
}
}

if ((total > max_songs)&&(have_equipped($item[ittah bittah hookah])))
{
cli_execute("unequip ittah bittah hookah");
equip($item[ittah bittah hookah]);
total -= 1;
}

Rinn
07-10-2010, 01:09 AM
Someone attach a script with your updated changes and I'll bump the version number with it.

tgetgel
09-13-2010, 05:58 PM
How can I incorporate this in a mood. For example, if I am running a "meat" mood which checks for the Polka of Plenty buff, I would want the solution, when my mood triggers due to the effect running out, to check to see if I can cast the buff myself, or run this script requesting the buff.

Pseudo code
mood triggers for a specific buff
can I cast buff?
---yes - cast buff, end check or next mood trigger
---no - set zlib value for buff, request buff
was buff requested?
---yes-end check or next mood trigger
---no-abort/print message and stop current activity (maybe continue without the buff to the next mood trigger?)

The reason for the zlib value change is that not all buffs cost the same. It would change the value before the specific buff was requested. Is there a local global data list that can be edited for the value limit? The script would use the list value for the buff as the zlib limit.

slyz
09-13-2010, 07:07 PM
There are several ways to do this: you could write a betweenBattleScript that handles your moods instead of the built-in Mafia functionality. It wouldn't be as flexible though.

You could also execute some ASH via a command in your Mood. For example:

Trigger On: When an effect is lost
Check For: Polka of Plenty
Command: import "acquireBuff.ash"; effect ef=$effect[Polka of Plenty];skill sk=to_skill(ef); if(have_skill(sk)){use_skill(1,sk);exit;} if(!acquireBuff(ef))abort("Could not get turns of "+ef);

Unfortunately, this will wait until you get an effect before asking for the next one. Doing what you are thinking of would require an important rewrite of Rinn's acquireBuff.

I have this aliased:


rbuff => ashq import 'acquirebuff.ash'; acquireBuff($effect[%%]);


You could put the command I wrote above in an alias, like this:


rbuff => ashq import "acquireBuff.ash"; effect ef = $effect[%%];skill sk = to_skill(ef);if(have_skill(sk)){use_skill(1,sk);ex it;}if(!acquireBuff(ef))abort("Could not get turns of "+ef);

and simply use this to add something in your mood:

Trigger On: When an effect is lost
Check For: Polka of Plenty
Command: rbuff Polka of Plenty

I didn't understand the bit about the zlib value though. The ones set in Rinn's script don't need to be modified in function of the buff? If you want to set a new max price, do not edit acquireBuff.ash, just type zlib acquireBuff_max_price = 5000 in the gCLI.

tgetgel
09-14-2010, 02:39 AM
Thanks, slyz. That is what I was hoping could be done.


I didn't understand the bit about the zlib value though. The ones set in Rinn's script don't need to be modified in function of the buff? If you want to set a new max price, do not edit acquireBuff.ash, just type zlib acquireBuff_max_price = 5000 in the gCLI.

The thought was if I am only willing to spend x on Polka of Plenty, y on The Ode to Booze, but z on Bubbly Ballad, I would then preset the zlib limit for that buff before trying to aquire it. Like if I was cash strapped and did not want to spend more than a certain limit for a specific buff. I wanted to limit how much could be spent on an inexpensive buff in case the less expensive bots were offline without prohibiting an expensive buff from being acquired.


Trigger On: When an effect is lost
Check For: Polka of Plenty
Command: rbuff Polka of Plenty


rbuff => ashq import "acquireBuff.ash"; effect ef = $effect[%%];
"zlib acquireBuff_max_price = {using file/effectvalue|value_of_effect[ef]}";
skill sk = to_skill(ef); if(have_skill(sk)){use_skill(1,sk);exit;}
if(!acquireBuff(ef))abort("Could not get turns of "+ef);

This would require some sort of file/list with the effect names and some value that can be accessed in the alias. I hope that helps explain.

I just don't know how to write the code as you can probably tell by my bolded insert above.

oly0015
09-14-2010, 04:38 AM
Yeah i know the feeling, when i was working on the same problem i designed a script to refill the buffs kinda like a between battle script using a improved version of this code. In mine though i just run the buffs from a datafile thats made by a webpage. It would be nice to just be able to grab the buff list from mood management but its not possible currently.

Rinn
01-09-2011, 06:02 AM
I've updated this to check if you have too many at songs before requesting.

oly0015
01-09-2011, 11:27 PM
This is a bit of an update I did awhile ago, handles a lot of the AT song problems

Rinn
01-10-2011, 09:52 AM
I just found a case where the script didn't think I had the four songs modifier when I did so it didn't request a buff, I'll look into fixing it in the next couple days.

razorboy
02-15-2011, 05:41 AM
So I just switched over to using this library for requesting buffs, but I'm running into some wierdness.

This is how I'm calling it:
"acquireBuff2 Carlweather's Cantata of Confrontation"

And I seem to get an infinite loop... I understand waiting for the buff, but it seems to send kmail every 30 seconds.

> Checking for updates (running ZLib ver. : 22)...
> You have a current version of ZLib.
> AcquireBuff.ash made by rinn, updated by oly0015
> So it seems you need Carlweather's Cantata of Confrontation
> Attempting to get the song Carlweather's Cantata of Confrontation
> Carlweather's Cantata of Confrontation
> Refreshing buffbot data...
> Buffbot data refreshed.
> Previous value of acquireBuff_last_update: 20110214
> Changed to 20110215.
> Sending kmail to Noblesse Oblige for 4meat

send a kmail to Noblesse+Oblige: 4 Meat
> Refreshing buffbot data...
> Buffbot data refreshed.
> Previous value of acquireBuff_last_update: 20110215
> Sending kmail to Noblesse Oblige for 4meat

send a kmail to Noblesse+Oblige: 4 Meat
> Refreshing buffbot data...
> Buffbot data refreshed.
> Previous value of acquireBuff_last_update: 20110215
> Sending kmail to Noblesse Oblige for 4meat

send a kmail to Noblesse+Oblige: 4 Meat
> Refreshing buffbot data...
> Buffbot data refreshed.
> Previous value of acquireBuff_last_update: 20110215
> Sending kmail to Noblesse Oblige for 4meat

slyz
02-15-2011, 06:38 AM
To avoid retrieving the buffbot data at each try, replace line 114


cli_execute("zlib acquireBuff_last_update = " + today_to_string());

with


vars["acquireBuff_last_update"] = today_to_string();
updatevars();


Another issue is that the script should try a first online bot (as determined by is_online()), and try the next one if you don't get the buff after waiting. The problem is that gather_data() is called at each try, and gather_data() resets the "online" flag that was meant to be switched off to skip the buffbot on the next iteration.

The best way to avoid this would be to only call gather_data() only once, from the top level so it is called even if another script imports acquireBuff.ash. Simply move line 210


gather_data();

to the top level (on line 100 for example, right after the function is defined).

Rinn
10-27-2011, 06:05 PM
It only took 8 months but I updated the script with Slyz's fixes.

Rinn
11-02-2011, 05:34 PM
I fixed an issue that wasn't causing the four songs modifier to get rechecked (because it was in the top level). I'll update it in a second.