Bug - Fixed Invalid setting 5 for choiceAdventure670

Veracity

Developer
Staff member
OK. How are you using this? If you are automating X turns in the Basement, that 5th choice will not take a turn, but will go back to the choice next adventure. Which is to say, it will loop forever, unless you have "1 choiceadv" or something as your condition. That seems dangerous for something you can select from the UI.

Now, if you are scripting, you could set the basement choices that need the umbrella or the amulet to exit the choice, set a "1 choiceadv" condition, and when automation stops, see what the last choice was and equip the appropriate item, and adventure once to open the Ground Floor.

That seems reasonable, but you don't need the UI to set those options, do you?

Why would it be usaful to have the choices in the UI?
 

Malibu Stacey

Active member
The UI isn't the problem, the repeated error when choiceAdventure670 == 5 is.
In autoscend it's used by checking the lastAdventure property and setting it to something else depending on whether we have the umbrella or amulet once we've hit that adventure so we always want it to be 5 the first time (it attempts to pull or farm one of those if it doesn't have them and leaves that zone primed). This is Cheesecookies's old code from what I can see and I haven't had a chance to move it to the choiceAdventureScript yet (lots of other more pressing places to handle before the level 10 quest). I would personally do this differently but we live with it for now.

And we're worried about infinite loops due to choice adventure settings, there are a few places that this is possible e.g. Barf Mountain.
 

Veracity

Developer
Staff member
Here is what I would expect your script to be doing:

Code:
// Set options for the three Basement choice adventures.
set_property( "choiceAdventure669", "5" );	// The Fast and the Furry-ous => exit and come back with umbrella
set_property( "choiceAdventure670", "5" );	// You Don't Mess Around with Gym => exit and come back with amulet
set_property( "choiceAdventure671", "4" );	// Out in the Open Source => to Fitness Choice (670)

// We want to adventure until we take a choice
cli_execute( "conditions clear" );
cli_execute( "conditions add 1 choiceadv" );

// Adventure until we take a choice
while ( goal_exists( "choiceadv" ) ) {
    // Do up to 10 adventures at a time. Whatever.
    adventure( $location[ The Castle in the Clouds in the Sky (Basement) ], 10 );
}

// See what choice we took
item needed = $item[ none ];
switch ( get_property( "lastEncounter" ) ) {
case "The Fast and the Furry-ous":
    set_property( "choiceAdventure669", "4" );
    needed = $item[ titanium assault umbrella];
    break;
case "You Don't Mess Around with Gym":
    set_property( "choiceAdventure670", "4" );
    needed = $item[ amulet of extreme plot significance];
    break;
}

// Adventure to retrieve the item we need
cli_execute( "conditions clear" );
add_item_condition( 1, needed );
while ( goal_exists( "item" ) ) {
    // Do up to 10 adventures at a time. Whatever.
    adventure( $location[ The Penultimate Fantasy Airship ], 10 );
}

// We have the item. Go back to the basement and open the Ground Floor
adventure( $location[ The Castle in the Clouds in the Sky (Basement) ], 1 );
Now, that is simplified:

- It doesn't check for running out of adventures.
- It doesn't account for Wiener Dog or Turtle Taming choice adventures, either of which will satisfy the "1 choiceadv" condition.

FWIW, VMF has a "adventure_until_choice" function which is used to deal with the Barf Mountain's choice

Code:
void do_adventure_until_choice( int turns, location loc, int goal )
{
    if ( my_inebriety() > inebriety_limit() ) {
	return;
    }

    string url = loc.to_url();
    string filter = choose_combat_filter( loc );

    boolean adventure_until_choice( int turns )
    {
	while ( turns > 0 ) {
	    between_battle_checks();
	    string page = visit_url( url );
	    if ( page.contains_text( "fight.php" ) ) {
		// Combat
		combat_filter_setup( loc );
		run_combat( filter );
		turns--;
	    } else if ( page.contains_text( "choice.php" ) ) {
		// Choice
		int choice = last_choice();
		// Take default option
		run_choice( -1 );
		// If this was the choice we sought, done
		if ( choice == goal ) {
		    return true;
		}
		// *** In Barf Mountain, the only choice is the one we seek
		// *** In other locations, other turn-using choices exist
		// *** Depending on options, may not use turns.
		// Turtle taming or ghost dog do not consume a turn.
	    } else {
		// Non-Combat
		turns--;
	    }
	}
	return false;
    }
... stuff that calls adventure_until_choice(), repeatedly, accounting for counters and such...
}
That doesn't even use goals or conditions or "adventure" (or "adv1"); it goes all the way down to visit_url() and does run_combat() or run_choice(), as needed.

And, as you mentioned, you could probably use a choiceAdventureScript.

So, I'm still wondering what the issue is with "Cheesecookie's old code". You can avoid infinite loops on the choice using conditions ("1 choiceadv") and adventure(). What is your code doing differently?

And regarding the UI, yes, we could/should fix the GUI:

Code:
		// The Fast and the Furry-ous
		new ChoiceAdventure(
			"Beanstalk", "choiceAdventure669", "Basement Furry",
			new Object[] { "Open Ground Floor with titanium umbrella, otherwise Neckbeard Choice", "200 Moxie substats",
				"???", "skip adventure and guarantees this adventure will reoccur" } ),

		// You Don't Mess Around with Gym
		new ChoiceAdventure(
			"Beanstalk", "choiceAdventure670", "Basement Fitness",
			new Object[] { new Option( "massive dumbbell, then skip adventure", "massive dumbbell" ),
				       "Muscle stats",
				       "Items",
				       "Open Ground Floor with amulet, otherwise skip" } ),

		// Out in the Open Source
		new ChoiceAdventure(
			"Beanstalk", "choiceAdventure671", "Basement Neckbeard",
			new Object[] { new Option( "With massive dumbbell, open Ground Floor, otherwise skip adventure", "massive dumbbell" ),
				       "200 Mysticality substats",
				       "O'RLY manual, open sauce",
				       "Fitness Choice" } ),
The options could stand some improvement, but, as we agree, it isn't really the GUI which is an issue here for your script.
 

Veracity

Developer
Staff member
The UI isn't the problem, the repeated error when choiceAdventure670 == 5 is.
So the issue is that you have a choice option set which exits the choice without advancing a turn and if you adventure again, it gets the same choice.
Yes, Barf Mountain has a similar choice.

I just poked through the autoscend code to see what you are doing.

Interesting lines in L10_Basement:

Code:
set_property("choiceAdventure670", "5"); // You Don't Mess Around with Gym: Open Ground floor (with amulet)
set_property("choiceAdventure671", "4"); // Out in the Open Source: Go to Fitness Choice
set_property("choiceAdventure669", "4"); // The Fast and the Furry-ous: Skip (and ensure reoccurance)
choice 670/5 will exit and force reoccur (need amulet)
choice 669/4 will skip and force reoccur (need umbrella)

How do you adventure here?

Code:
autoAdv(1, $location[The Castle in the Clouds in the Sky (Basement)]);
That function does this:

Code:
retval = adv1(loc, -1, option);
In other words, you set various whichchoice properties and do adv1.

Back in L10_basement:

Code:
	if(contains_text(get_property("lastEncounter"), "The Fast and the Furry-ous"))
	{
		auto_log_info("We was fast and furry-ous!", "blue");
		autoEquip($item[Titanium Assault Umbrella]);
		set_property("choiceAdventure669", "1"); // The Fast and the Furry-ous: Open Ground floor (with Umbrella)
		autoAdv(1, $location[The Castle in the Clouds in the Sky (Basement)]);
and

Code:
	else if(contains_text(get_property("lastEncounter"), "You Don\'t Mess Around with Gym"))
	{
		auto_log_info("Just messed with Gym", "blue");
		...
		set_property("choiceAdventure670", "5"); // You Don't Mess Around with Gym: Open Ground floor (with amulet)
		...
		set_property("choiceAdventure670", "4"); // You Don't Mess Around with Gym: Open Ground floor (with amulet)

		if(!autoEquip($slot[acc3], $item[Amulet Of Extreme Plot Significance]))
		{
			abort("Unable to equip the Amulet when we wanted to...");
		}
		autoAdv(1, $location[The Castle in the Clouds in the Sky (Basement)]);
	}
This is peculiar code. You are willing to pull or back farm for an amulet, but if you don't have a titanium umbrella, you get the dumbbell. Seems like if you are willing to pull an amulet, perhaps you could be willing to pull an umbrella. Whatever. I'm just trying to understand how you are dealing with choices and adventuring.

Since this only adventures once - unless you get a choice that you can satisfy - there must be somewhere else that loops on this function, based on quest progress, I assume.

The essense of the issue is that you do this:

Code:
set_property("choiceAdventure669", "4"); // The Fast and the Furry-ous: Skip (and ensure reoccurance)
adv1 $location[The Castle in the Clouds in the Sky (Basement)], -1, "")

What does adv1 do?

Code:
			adventure.overrideAdventuresUsed( -1 );
			KoLmafia.redoSkippedAdventures = false;
			KoLmafia.makeRequest( adventure, 1 );
Looking at KoLmafia.makeRequest, that "redoSkippedAdventures = false" should mean that we do not insist on using 1 turn; a choice adventure that uses 0 turns - like this one - will not be repeated.

So I tried it out. I adventured via the GUI in the Castle BVasement until it got a choice.

Code:
[876912] The Castle in the Clouds in the Sky (Basement)
Encounter: The Fast and the Furry-ous
[color=red]Manual control requested for choice #669[/color]
choice 1: Crawl Through the Heating Duct (Neckbeard Choice (titanium umbrella not equipped))
choice 2: Check out the Furry's Figurine Collection (200 Moxie substats)
choice 4: Leave Through a Mousehole (skip adventure and guarantees this adventure will reoccur)
[color=red]Click here to continue in the relay browser.[/color]

[color=green]> choice 4[/color]
I set that choice option to force reoccurance

Code:
[color=green]> get choiceAdventure669[/color]

0

[color=green]> get choiceAdventure669=4[/color]

choiceAdventure669 => 4
And then I adventured using adv1, just like autoscend does:

Code:
[color=green]> debug on[/color]

[color=green]> ashq adv1( $location[The Castle in the Clouds in the Sky (Basement)], -1, "" )[/color]

Visit to Beanstalk: The Castle in the Clouds in the Sky (Basement) in progress...

[876912] The Castle in the Clouds in the Sky (Basement)
Encounter: The Fast and the Furry-ous

Requests complete.

[color=green]> choice[/color]

[color=red]You aren't in a choice adventure.[/color]

[color=green]> debug off[/color]
It worked fine. The DEBUG log (and my session log) confirms that it took the choice and stopped adventuring.

Code:
[876912] The Castle in the Clouds in the Sky (Basement)
Encounter: The Fast and the Furry-ous
Took choice 669/4: skip adventure and guarantees this adventure will reoccur
choice.php?whichchoice=669&option=4&pwd
So I am confused about what you want me to do.

1) There is a missing choice option in the GUI for choice adventure 670.

Code:
		new ChoiceAdventure(
			"Beanstalk", "choiceAdventure670", "Basement Fitness",
			new Object[] { new Option( "massive dumbbell, then skip adventure", "massive dumbbell" ),
				       "Muscle stats",
				       "Items",
				       "Open Ground Floor with amulet, otherwise skip" } ),
You are correct; you cannot set option 5 via the GUI. Note that we have "dynamic" spoilers for that choice:

Code:
		case 670:
			// You Don't Mess Around with Gym
			result = new Object[ 5 ];
			result[ 0 ] = "massive dumbbell, then skip adventure";
			result[ 1 ] = "200 Muscle substats";
			result[ 2 ] = "pec oil, giant jar of protein powder, Squat-Thrust Magazine";
			result[ 3 ] =
				KoLCharacter.hasEquipped( ItemPool.get( ItemPool.EXTREME_AMULET, 1 ) ) ?
				"open Ground Floor (amulet equipped)" :
				"skip adventure (amulet not equipped)";
			result[ 4 ] = "skip adventure and guarantees this adventure will reoccur";
			return result;
So that in the Relay Browser - or in the gCLI, if you wanted manual control - it will show you all options.

So, sure - I can add the last option to what you see in the choice option configuration. That will be consistent with choice 669, which gives a choice which will reoccur.

2) If you adventure via the GUI or via adventure() in ASH, if you have those options set like that, KoLmafia will loop, since in those cases, the "redoSkippedAdventures" flag will be true.
Unless you have set "1 choice" as a goal/condition to stop on. Not doing that is a user error, in my opinion.

3) But my testing shows that adventuring using adv1() will (correctly) take the choice and return. Looking at autoscend, it sure looks like it is using adv1, so there should be no infinite loop.

tldr; the only bug I see is a missing choice option in the GUI configuration of choice #670 - which is literally all you said in your original post.

So I will fix this and declare this done. :)
 
Top