Bounty! 2 million meat for macro!

StDoodle

Minion
My frustration over this has certainly come to a middle. Suppose you have this KoL combat macro:
Code:
abort hppercentbelow 20
if hasskill entangling noodles
  skill entangling noodles
endif
while mppercentbelow 99 && !pastround 10
  use seal tooth
endwhile
while !pastround 15 && !hppercentbelow 60
  use spices
endwhile
skill shieldbutt
repeat
How would one submit this from a fight.php override? I don't care which version of visit_url() is used, I don't care what encoding / decoding functions are used (built-in or custom), I just want to use that macro in a script*. I will pay 1 million meat to the first person to offer a solution. Note: solutions that involve a patch to KoLmafia's source are considered to be submitted when the patch is incorporated into KoLmafia according to the SVN log. To anyone interested, I have found a few ways that appear to work, but actually ignore the second macro predicate following any "&&"; so I'll be checking.

Additional notes: while I can't imagine why it would matter, it must be possible to have the macro text saved as a string or buffer. Again, can't see that it should happen, but any solution which breaks upon using a variable in visit_url() to hold all or part of the submitted url will not be considered complete.

Thanks, and good luck.

*Well, not actually that macro, but it's a very useful test-case.

P.S. Special thanks to zarqon for the "standard" of using mu (μ) as the meat-currency symbol.
 
Last edited:

xKiv

Active member
To anyone interested, I have found a few ways that appear to work, but actually ignore the second macro predicate following any "&&"; so I'll be checking.

Are you *completely* sure the second macro predicate is not ignored even in vanilla kol?
My memory on this is hazy, but I think there are still a few unexpected wrinkles in there ...
 

StDoodle

Minion
100%. Trust me, after my failure to properly test "ANDAND" I'm not reporting a macro as working unless I've checked all combinations I can think of. ;)
 

Rinn

Developer
Can I see what you tried already that you had issues with? I have an idea I'm gonna try after rollover and seeing some code you already tried would help.
 
Last edited:

heeheehee

Developer
Staff member
Code:
buffer visit_url( string, boolean, boolean )
Code:
public static Value visit_url( final Value string, final Value usePostMethod, final Value encoded )
Hmm...
Code:
ash print(visit_url("fight.php?action=macro&macrotext=abort+hppercentbelow+20%0D%0Awhile+mppercentbelow+99+%26%26+%21pastround+10%0D%0A++use+seal+tooth%0D%0Aendwhile%0D%0Awhile+%21pastround+15+%26%26+%21hppercentbelow+20%0D%0A++use+spices%0D%0Aendwhile%0D%0Arepeat&whichmacro=0", true, true));

Yeah, I have no idea when the three-parameter version of visit_url() was added. Someone should get around to adding that to the wiki... *whistles*
 

StDoodle

Minion
Ugh, just ascended, so I can't test that... does it work? Really? Was it the lack of the "whichmacro" part? I don't know why that would be needed, but hey; if it works!
 

heeheehee

Developer
Staff member
Might be the three-parameter version, which is false by default... but I have no idea if you tried that or not.

As for what the fields contained, I just set macroLens to true and captured the postdata, then changed the value of the hpbelow predicate a few times. Seemed to work, as far as I could tell.
 

StDoodle

Minion
Cool, I'll test this myself in a day or two (when I'm high enough level to make it work) and send your meat if it works!
 

Veracity

Developer
Staff member
The three-argument version was inserted on 13 Nov 2010 in revision 8767. It was created to deal with relay scripts which wanted to submit precisely a URL that was attached to a button or something - which was, therefore, already url-encoded. The revision history says this:

Add a three-argument form of visit_url:
visit_url( string location, boolean usePostMethod, boolean encoded );
The third argument indicates whether the &-separated fields in the location are
already url_encoded. If not, KoLmafia will split out the fields at & boundaries
and encode them, as before.
You probably won't need to use this unless your field values contain a &.

I direct you to this thread (which mentions that "I was just talking to St. Doodle about something". In particular, it was your relay script. In other words, I originally added 8767 for YOU.

It sounds like you want/need to use it for urls that you are hand-crafting yourself that contain the & character. So, take the macro and url_encode it and use the 3-argument version, just as hee**3 suggested.

Taking hee**3's example and doing it the RIGHT way (i.e., telling ASH to url-encode for you, rather than manually doing it :) ), I get:

Code:
ash string macro="whatever"; print( visit_url( "fight.php?action=macro&macrotext=" + url_encode( macro ) + "&whichmacro=0", true, true )

Where, obviously, macro is whatever you want it to be - including &'s at will.
 

StDoodle

Minion
Yeah, I wasn't trying to bash you or anything V; I was just getting frustrated that there must still be something I was missing; turns out it was the "&whichmacro=0" part, which... I still don't get, but if that makes it work, awesome! (I was using the documentation on the GD thread, which never mentioned that particular url parameter, that I saw.)

I imagine I probably ticked you off when I said:
My frustration over this has certainly come to a middle.
But that's actually paraphrasing a line from Firefly; it's meant to be a joke. Sorry.
 

Bale

Minion
Firefly quotes are rarely appreciated by those who are not brownshirts, which excludes too many people. I thought it was amusing even though it was badly mutilated from its original form, but I might be the only one here.

I'm not sure if your bounty belongs to Veracity who added a feature to KoL just so that you could use an ampersand in your URL or heeheehee who found that feature.
 

StDoodle

Minion
Well, it wasn't using that feature that was the issue; I was already pretty sure it was necessary for pulling this off. (And grateful for it's existence!) It was the missing "whichmacro=0" in the url that seems to have borked my attempts. Basically, once again, I failed at something rather simplistic and obvious, and proceeded to come up with a bunch of wonky workarounds that were completely unnecessary. And apparently managed to tick of V in the process... even though it's just me being stupid!

Edit to add:
Well, tested today. Still no luck. Using this:
Code:
page = visit_url( "fight.php?action=macro&macrotext=" + url_encode( "attack;repeat" ) + "&whichmacro=0", true, true );
Which is exactly what Veracity gave, minus the print() (not sure what hee3 put that in for...) with a preset macro of the simplest nature, and saving the result. Also tried with "\r\n" and "\n" in place of ";".
Code:
Invalid macro command encountered:
"attack%3Brepeat"
So, back to my original question... shouldn't this work? Is there something else that I'm missing? Please feel free to call me nine kinds of idiot for whatever it is I'm still doing wrong, it's just really starting to get to me that this isn't working. I dunno...

EDIT TO ADD:
Ok, riddle me this... the above listed methods work just fine from the cli... but try to use them in a fight.php override, and it's a no-go. Huh?
 
Last edited:

fronobulax

Developer
Staff member
Firefly quotes are rarely appreciated by those who are not brownshirts, which excludes too many people. I thought it was amusing even though it was badly mutilated from its original form, but I might be the only one here.
Badly enough that I still don't recognize the reference but maybe I just don't watch it enough to have vast sections of dialog memorized.
 

Veracity

Developer
Staff member
OK, there is something funky going on.

I added a new ash function: string make_url( string location, boolean use_post_method, boolean encoded );
This takes the same arguments as the 3-argument version of visit_url but simply crafts the url string the same way that the latter function does and returns it without submitting it.

Here's a test script:

Code:
buffer mbuf;
mbuf.append( "pickpocket\n" );
mbuf.append( "attack\n" );
mbuf.append( "repeat" );

string macro = mbuf.to_string();

buffer new_url;
new_url.append( "fight.php" );
new_url.append( "?" );
new_url.append( "action=macro" );
new_url.append( "&" );
new_url.append( "macrotext=" );
new_url.append( macro );

print( "crafted unencoded url = \"" + new_url + "\"");
print( "submitted url = \"" + make_url( new_url, true, false ) + "\"" );

new_url.set_length( 0 );
new_url.append( "fight.php" );
new_url.append( "?" );
new_url.append( "action=macro" );
new_url.append( "&" );
new_url.append( "macrotext=" );
new_url.append( url_encode( macro ) );
print( "crafted encoded url = \"" + new_url + "\"");
print( "submitted url = \"" + make_url( new_url, true, true ) + "\"" );

which does this:

> url.ash

crafted unencoded url = "fight.php?action=macro&macrotext=pickpocketattackrepeat"
submitted url = "fight.php?action=macro&macrotext=pickpocket%0Aattack%0Arepeat"
crafted encoded url = "fight.php?action=macro&macrotext=pickpocket%0Aattack%0Arepeat"
submitted url = "fight.php?action=macro&macrotext=pickpocket%0Aattack%0Arepeat"
Note that the "encoded" argument works as one might hope: if you have not already url_encoded the argument, say encoded=false and we encode it for you, otherwise, say encoded=true and we pass it through untouched. The resulting url is identical.

Yet, when my fight.ash relay override tried submitting that, we actually submitted:

Requesting: http://www4.kingdomofloathing.com/fight.php?action=macro&macrotext=pickpocket%250Aattack%250Arepeat

%0A turned into %250A - which is to say, the "%" was url_encoded into %25.

Something is screwy. Investigating.
 

Veracity

Developer
Staff member
Ha ha ha ha ha ha ha ha.

OK, got it. Believe it or not, the three argument version of visit_url correctly encodes and submits the url - unless you are in a relay script, in which case it acts like the one argument version. With that fixed, this fight.php relay override:

PHP:
void main()
{
	string [string] fields = form_fields();

	buffer url;
	string sep = "?";
	url.append( "fight.php" );
	if ( count(fields) > 0 ) {
		foreach field, val in fields {
			url.append( sep );
			sep = "&";
			url.append( field );
			url.append( "=" );
			url.append( val );
		}
	}
	print( url );

	string page = visit_url();

	// if this was the original page visit, submit a macro to finish
	// the battle.
	if ( fields contains "ireallymeanit" ) {
		buffer macro;

		macro.append( "abort hppercentbelow 20\n");
		macro.append( "pickpocket\n" );
		macro.append( "while mppercentbelow 99 && !pastround 10\n" );
		macro.append( "  use seal tooth\n" );
		macro.append( "endwhile\n" );
		macro.append( "while !pastround 15 && !hppercentbelow 60\n" );
		macro.append( "  use spices\n" );
		macro.append( "endwhile\n" );
		macro.append( "attack\n" );
		macro.append( "repeat" );

		buffer new_url;
		new_url.append( "fight.php" );
		new_url.append( "?" );
		new_url.append( "action=macro" );
		new_url.append( "&" );
		new_url.append( "macrotext=" );
		new_url.append( url_encode( macro ) );
		print( new_url );
		page = visit_url( new_url, true, true );
	}

	write(page);
}
does this:

fight.php?ireallymeanit=1295974230

[292638] Giant's Castle
Encounter: Raver Giant
Round 0: Brianna wins initiative!
fight.php?action=macro&macrotext=abort+hppercentbelow+20%0Apickpocket%0Awhile+mppercentbelow+99+%26%26+%21pastround+10%0A++use+seal+tooth%0Aendwhile%0Awhile+%21pastround+15+%26%26+%21hppercentbelow+60%0A++use+spices%0Aendwhile%0Aattack%0Arepeat
Round 1: Brianna executes a macro!
Round 1: Brianna tries to steal an item!
Round 2: Brianna uses the spices!
Round 3: Brianna uses the spices!
Round 4: raver giant takes 1 damage.
Round 4: Brianna uses the spices!
Round 5: raver giant takes 1 damage.
Round 5: Brianna uses the spices!
Round 6: Brianna uses the spices!
Round 7: Brianna uses the spices!
Round 8: Brianna uses the spices!
Round 9: Brianna uses the spices!
Round 10: Brianna uses the spices!
Round 11: raver giant takes 1 damage.
Round 11: Brianna uses the spices!
Round 12: raver giant takes 1 damage.
Round 12: Brianna uses the spices!
Round 13: Brianna uses the spices!
You lose 22 hit points
Round 14: Brianna uses the spices!
Round 15: raver giant takes 1 damage.
Round 15: Brianna uses the spices!
Round 16: raver giant takes 1 damage.
Round 16: Brianna attacks!
Round 17: Brianna attacks!
Round 18: Brianna attacks!
You lose 15 hit points
Round 19: Brianna attacks!
Round 20: raver giant takes 1413 damage.
Round 20: Brianna wins the fight!
After Battle: Gort winks at you.
You gain 345 Meat
You acquire an item: Angry Farmer candy
You gain 5 Strengthliness
You gain 10 Enchantedness
You gain 20 Smarm

I'll submit a fix in a few minutes.

Edit: (In case you are wondering why there were several rounds of attack with nothing happening, I have one word: Cunctatitis)
 
Last edited:

StDoodle

Minion
I dunno, I'm a noob on Java*, but I tried double-checking GenericRequest.java and FightRequest.java and don't see anywhere where the encoding shouldn't do what it's told. The only thing that sticks out in my mind is that FightRequest's nextRound() doesn't use the "encoded" parameter, but for the life of me I can't figure out exactly how nextRound() is used, so... I'm probably way off. *shrug*

I really appreciate you looking into this, though. I'm also glad to know it isn't just me going crazy...

*Or in many other matters...

Edit; and you ninja'd me while I was flailing wildly in an attempt to help, ha! Thank you!

Edit2: oh wait, is it those lines around the 1630's of \textui\RuntimeLibrary.java? No? /me scratches head...
 
Last edited:

Veracity

Developer
Staff member
P.S. I claim your bounty.

1) You need KoLmafia revision 8940 to fix visit_url; it was a one line fix in RuntimeLibrary.java to line 1654
2) You do not need to manually url_encode your macro; simply pass it to url_encode and use the three argument version of visit_url with encoded=true.
3) You do not need "&whichmacro=0"

See my sample fight.php relay override script.
 
Top