Bug - Not A Bug while loops and the ticket counter possibly locking up mafia

fianor

Member
This:

while ( item_amount( $item[coffee pixie stick] ) <3)
cli_execute("acquire coffee pixie stick");


completely locks up mafia and eats about 50% of my CPU. I have to kill mafia in task manager when this happens. It happens every single time without fail for me. I have the latest mafia and updated java this morning. It's not new to the latest builds though. I also got the same issue while running

while coffee pixie stick < 3; acquire coffee pixie stick

from a cli script. Because of this I'm guessing that it has to do with a while statement & the ticket counter in combination. The while at least begins to work as it sees that I have less than 3 of them and trades for the first one, then it locks up before ever getting the 2nd.





BTW this:

if ( item_amount( $item[coffee pixie stick] ) <3)
cli_execute("acquire coffee pixie stick");
if ( item_amount( $item[coffee pixie stick] ) <3)
cli_execute("acquire coffee pixie stick");
if ( item_amount( $item[coffee pixie stick] ) <3)
cli_execute("acquire coffee pixie stick");

works just fine to pick up all 3 sticks.
 

Theraze

Active member
Try this:
Code:
if (item_amount( $item[coffee pixie stick] ) < 3)
retrieve_item((3 - item_amount( $item[coffee pixie stick] )), $item[coffee pixie stick]);

Problem with your second post is that it's an infinite loop... While (0 == 3) do nothing. Shouldn't have put the semi-colon in there. Generally, try to avoid the while loops if you aren't going to make sure your acquisition is possible otherwise or provide for breaks...
 
Last edited:

slyz

Developer
I think "acquire coffee pixie stick" will not get a new one if you already have one in your inventory. Why don't you use "acquire 3 coffee pixie stick"?
 

Veracity

Developer
Staff member
That is exactly right. "acquire x item" ensures that you have x of item in your inventory. If you already have x of them, it does nothing; it does NOT mean "get me x MORE of the item."

This is not a bug.
 

Theraze

Active member
And even if you're using the "acquire 3 coffee pixie stick" syntax, if you don't have the tickets and it can't acquire them, it'll go into an infinite loop because it doesn't have the tickets needed to break out of its loop. Definitely a case where if works better than while.
 

Bale

Minion
Just for the record,

Code:
[COLOR="#808000"]> ash retrieve_item(3, $item[coffee pixie stick] )[/COLOR]

Returned: false

You cannot acquire coffee pixie sticks because it is impossible to acquire Game Grid tickets. Any item that cannot be discarded will not be bought by mafia without a specific command to do so, unless it is a hardcoded exception to that rule. You actually need to do this:

PHP:
retrieve_item(3, $item[coffee pixie stick]);
if (item_amount( $item[coffee pixie stick] ) < 3) {
   buy(30 - 10* item_amount( $item[coffee pixie stick] ), $item[Game Grid ticket]);
   retrieve_item((3 - item_amount( $item[coffee pixie stick] )), $item[coffee pixie stick]);
}
 

fianor

Member
Code:
#*******************************************************************************
#                                DWSSpleen.ash v0.1
# ------------------------------------------------------------------------------
# This script obtains and consumes spleen items  for my optimum meat gain
# per day.  You will need to adjust it depending on what skills your character
# has access to.
# ------------------------------------------------------------------------------
# Notes:
# 1) MPA means "meat per adventure"
# 2) I use the global variable DWSAdvToday to keep track of what point my 
#     automated scripts have gotten to in case they crash out.  This ensures 
#     that my scripts don't double up and waste adv.
# 3) DWS - Donald Wade Sansing.  I use my initials as a unique identifier 
#     on all variables I ever use in any programming I do.  This allows me
#     always know instantly if a variable I'm debugging is something I did
#     or if I have to go figure out what someone else screwed up.
#*******************************************************************************
if ((to_float(get_property( "DWSAdvToday" ))) > 2) 
    abort("Something odd happened, Manually spleen up today."); 
if (my_spleen_use() > 0)
   print("You're spleen is having spasms.", "green");
else
{
    while ( item_amount( $item[twinkly wad] ) <3)
        buy(1, $item[twinkly wad] );    
    while ( item_amount( $item[game grid ticket] ) <30)
        buy(5, $item[game grid ticket] );    
    if ( item_amount( $item[coffee pixie stick] ) <3)
        cli_execute("acquire coffee pixie stick");
    if ( item_amount( $item[coffee pixie stick] ) <3)
        cli_execute("acquire coffee pixie stick");
    if ( item_amount( $item[coffee pixie stick] ) <3)
        cli_execute("acquire coffee pixie stick");
    use(3, $item[coffee pixie stick]);
    use(3, $item[twinkly wad]);
    set_property( "DWSAdvToday", 3 );
}

As there seems to be confusion, there's the whole script I run. I ensure I have the tickets before attempting to get the sticks. This script as written works just fine.

When I have my previously posted while loop in it locks up mafia.

Problem with your second post is that it's an infinite loop... While (0 == 3) do nothing. Shouldn't have put the semi-colon in there. Generally, try to avoid the while loops if you aren't going to make sure your acquisition is possible otherwise or provide for breaks...

I'm not arguing, just trying to understand. How is it an infinite loop. It never tests 0 == 3, it tests count < 3.

Slyz - That's not an issue, if you have enough GG tickets it will pick up another stick regardless of whether you already have one in inventory.



Veracity - "Acquire 3 coffee pixie sticks" was the first thing I tried to use as it works with every other item in the game I've ever tried it on. I realize how the acquire works. That said, I wasn't using "acquire 3" because in testing it would buy 1 and lock up mafia on me, both typing it manually in the cli or running it in a script. I assumed it was something to do with the ticket counter interface and not mafia which is why I wrote the script this way instead of reporting that as a bug.

Just now, while writing this post; I bought 30 tickets and tried "acquire 3" again, and it worked fine. So w/e was causing that is now gone and eliminates the issue, even if there is/was a bug it should never be encountered beyond testing this script written this way.


Bale - thanks for that, as always a better programmer makes script cleaner than I can.


Edit: This is my new version, thx Bale. Will be testing it out tomorrow when I have spleen again.

Code:
#*******************************************************************************
#                                DWSSpleen.ash v0.2
# ------------------------------------------------------------------------------
# This script obtains and consumes spleen items  for my optimum meat gain
# per day.  You will need to adjust it depending on what skills your character
# has access to.
# ------------------------------------------------------------------------------
# Notes:
# 1) MPA means "meat per adventure"
# 2) I use the global variable DWSAdvToday to keep track of what point my 
#	 automated scripts have gotten to in case they crash out.  This ensures 
#	 that my scripts don't double up and waste adv.
# 3) DWS - Donald Wade Sansing.  I use my initials as a unique identifier 
#	 on all variables I ever use in any programming I do.  This allows me
#	 always know instantly if a variable I'm debugging is something I did
#	 or if I have to go figure out what someone else screwed up.
#*******************************************************************************
if ((to_float(get_property( "DWSAdvToday" ))) > 2) 
	abort("Something odd happened, Manually spleen up today."); 
if (my_spleen_use() > 0)
   print("You're spleen is having spasms.", "green");
else
{
	if ( item_amount( $item[twinkly wad] ) <3)
		buy(3 - item_amount( $item[twinkly wad] ), $item[twinkly wad]);
	if (item_amount( $item[coffee pixie stick] ) < 3) {
		buy(30 - 10* item_amount( $item[coffee pixie stick] ), $item[Game Grid ticket]);
		retrieve_item((3 - item_amount( $item[coffee pixie stick] )), $item[coffee pixie stick]);
	}  
	use(3, $item[coffee pixie stick]);
	use(3, $item[twinkly wad]);
	set_property( "DWSAdvToday", 3 );
}
 
Last edited:

Theraze

Active member
Where I said 0 == 3, if your acquire doesn't manage to get up to 3 for some reason, it will fail. It then tries exactly the same thing that just failed, leaving it at the same number. The 0 as an example was if you started with no coffee pixie sticks, so you begin with 0, acquire 0 because something went wrong, and it checks if you have at least 3 now.

To explain how it works, I'll do the loop it's doing below:
It checks if you have at least 3 pixie sticks. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now. You don't, so it tries to acquire 3, fails, and it checks if you have at least 3 now.

That repeats until you get bored and end the task. Easy fix? Use an if instead of while, because you really only want it to run an acquire 3 once.
 

fianor

Member
Are you talking about my 3 if's version in the case that I don't have enough tickets on hand to purchase the sticks?

If so, ok I get how that's an infinite loop. If not I'm still completely lost.
 

Theraze

Active member
Yeah, I was talking about your
Code:
while ( item_amount( $item[coffee pixie stick] ) <3)
cli_execute("acquire coffee pixie stick");

Basically, if your acquire doesn't get you up to 3 for any reason, it will infinitely try to do acquire coffee pixie stick over and over and over again, despite it having failed the last 300 (or 300 thousand) times. If you feel the need to do it with a while loop, leave yourself some sort of an out... something more like:
Code:
int looping = 0;
while ( item_amount( $item[coffee pixie stick] ) < 3 && looping++ < 3)
cli_execute("acquire coffee pixie stick");

Edit:
I think you might want to recheck your ticket purchasing... if you try to purchase a negative amount, does it purchase multiple, or sell, or do something else unexpected?

Specifically, this:
Code:
if ( item_amount( $item[twinkly wad] ) <3)
buy(3 - item_amount( $item[twinkly wad] ), $item[twinkly wad]);
if (item_amount( $item[coffee pixie stick] ) < 3) {
buy(30 - 10* item_amount( $item[coffee pixie stick] ), $item[Game Grid ticket]);
retrieve_item((3 - item_amount( $item[coffee pixie stick] )), $item[coffee pixie stick]);
}

Should probably be more like this:
Code:
if ( item_amount( $item[twinkly wad] ) <3)
buy(3 - item_amount( $item[twinkly wad] ), $item[twinkly wad]);
if (item_amount( $item[coffee pixie stick] ) < 3) {
if (item_amount( $item[Game Grid ticket] ) < 30 ) buy(30 - 10* item_amount( $item[coffee pixie stick] ) - item_amount( $item[Game Grid ticket] ), $item[Game Grid ticket]);
retrieve_item((3 - item_amount( $item[coffee pixie stick] )), $item[coffee pixie stick]);
}
 
Last edited:

Veracity

Developer
Staff member
Code:
When I have my previously posted while loop in it locks up mafia.[/quote]
Yes. And we explained exactly why: "acquire 1 xxx" will do nothing at all if you already have at least 1 xxx. Therefore, using "acquire 1 xxx" in a "while xxx < 3" loop is an infinite loop - as you discovered.

[quote]Slyz - That's not an issue, if you have enough GG tickets it will pick up another stick regardless of whether you already have one in inventory.[/quote]
No it won't.

[quote][color=green]> inv ticket[/color]

Game Grid ticket (20)

[color=green]> inv coffee pixie stick[/color]

[color=green]> acquire 1 coffee pixie stick[/color]

Visiting the Ticket Counter...
You acquire an item: coffee pixie stick
Ticket Counter successfully looted!

[color=green]> inv ticket[/color]

Game Grid ticket (10)

[color=green]> inv coffee pixie stick[/color]

coffee pixie stick

[color=green]> acquire 1 coffee pixie stick[/color]

[color=green]> acquire 1 coffee pixie stick[/color][/quote]

[quote]Veracity - "Acquire 3 coffee pixie sticks" was the first thing I tried to use as it works with every other item in the game I've ever tried it on.  I realize how the acquire works.  That said, I wasn't using "acquire 3" because in testing it would buy 1 and lock up mafia on me,  both typing it manually in the cli or running it in a script.  I assumed it was something to do with the ticket counter interface and not mafia which is why I wrote the script this way instead of reporting that as a bug.[/quote]
My test:

[quote][color=green]> inv ticket[/color]

Game Grid ticket (30)

[color=green]> inv coffee pixie stick[/color]

[color=green]> acquire 3 coffee pixie stick[/color]

Visiting the Ticket Counter...
You acquire coffee pixie stick (3)
Ticket Counter successfully looted!

[color=green]> inv ticket[/color]

[color=green]> inv coffee pixie stick[/color]

coffee pixie stick (3)

[color=green]> buy 10 game grid ticket[/color]

Searching for "game grid ticket"...
Purchasing Game Grid ticket (10 @ 348)...
You acquire Game Grid ticket (10)
Purchases complete.

[color=green]> acquire 4 coffee pixie stick[/color]

Visiting the Ticket Counter...
You acquire an item: coffee pixie stick
Ticket Counter successfully looted!

[color=green]> inv game grid ticket[/color]

[color=green]> inv coffee pixie stick[/color]

coffee pixie stick (4)[/quote]
It works fine.

[quote]Just now, while writing this post; I bought 30 tickets and tried "acquire 3" again, and it worked fine.  So w/e was causing that is now gone and eliminates the issue, even if there is/was a bug it should never be encountered beyond testing this script written this way.[/quote]
Nothing has changed in KoLmafia.
 

fianor

Member
Veracity -

You are of course correct , I had a basic misunderstanding of acquire and was not picking up on it from previous answers. Mostly likely I screwed something up when acquire 3 wasn't working for me and didn't realize it. Blame it on me being sick, the medicine I'm on, or me just being stupid, whichever suits your fancy.


Theraze -

You lost me again. I have no clue what happens if you try to buy -itemcount, my guess is mafia ignores you for being stupid and requesting stupid things.

What I don't see is how my version would ever request to buy a negative amount of tickets. The only way it will ever buy tickets is if I have 0,1 or 2 sticks as a negative amount of sticks can't be in inventory and 3 or more skips the buying entirely. It can only request to buy 30, 20 or 10 tickets from the mall.

I can see that it would buy more tickets than I might need if I already have some in inventory. Your version solves that.

Code:
if ((to_float(get_property( "DWSAdvToday" ))) > 2) 
	abort("Something odd happened, Manually spleen up today."); 
if (my_spleen_use() > 0)
   print("You're spleen is having spasms.", "green");
else {
	if ( item_amount( $item[twinkly wad] ) < 3)
		buy(3 - item_amount( $item[twinkly wad] ), $item[twinkly wad]);
	if (item_amount( $item[coffee pixie stick] ) < 3) {
		buy(30 - 10* item_amount( $item[coffee pixie stick] ), $item[Game Grid ticket]);
		retrieve_item((3 - item_amount( $item[coffee pixie stick] )), $item[coffee pixie stick]);
	}
	use(3, $item[coffee pixie stick]);
	use(3, $item[twinkly wad]);
	set_property( "DWSAdvToday", 3 );
}
 

Veracity

Developer
Staff member
You know, I just checked to see if you could simply "acquire 3 coffee pixie stick" and have KoLmafia automatically buy you any necessary game grid tickets, if you have autoSatisfyWithMall enabled (which I never do, so I never considered it). Turns out, it didn't work for a couple of reasons:

- Game Grid tickets have an autosell price of 0, so KoLmafia will not automatically buy them for you, since they are not on the special list of 0 autosell items that are "cheap" enough to buy - phials, clovers, love songs, divine items, white rice, and so on. Game Grid tickets seem pretty "cheap" to me, so, why not?
- The special code to make "acquire" go to the ticket counter for coffee pixie sticks specifically looked at your ticket count in inventory rather than recursively using retrieveItem to get the correct amount.

I fixed both of those and now it works like this:

> inv coffee pixie stick

coffee pixie stick (5)

> inv game grid ticket

Game Grid ticket (7)

> set autoSatisfyWithMall=true

autoSatisfyWithMall => true

> acquire 9 coffee pixie stick

Searching for "game grid ticket"...
Purchasing Game Grid ticket (33 @ 300)...
You acquire Game Grid ticket (33)
Purchases complete.
Visiting the Ticket Counter...
You acquire coffee pixie stick (4)
Ticket Counter successfully looted!

> inv coffee pixie stick

coffee pixie stick (9)

> inv game grid ticket

> set autoSatisfyWithMall=false

autoSatisfyWithMall => false
Revision 8708.
 

fianor

Member
so I can now just replace

Code:
	if (item_amount( $item[coffee pixie stick] ) < 3) {
		if (item_amount( $item[game grid ticket] ) < 30) 
			buy(30 - 10* item_amount( $item[coffee pixie stick] ) - item_amount( $item[game grid ticket] ), $item[Game Grid ticket]);
		retrieve_item((3 - item_amount( $item[coffee pixie stick] )), $item[coffee pixie stick]);
	}

with this?

cli_execute("acquire 3 coffee pixie stick")



-------------------

Also, is there a way to get mafia to return the value of a variable from the gcli without me adding a line like this

print ("Acquire includes mall? " + get_property( "autoSatisfyWithMall" ));

to a script and running it?
 

Veracity

Developer
Staff member
You can do that, or do it all within ASH via:

retrieve_item( 3, $item[ coffee pixie stick ] );

...which calls the identical internal function as the CLI "acquire" command.
 
Top