The Unofficial Ascend.ash support thread.

Theraze

Active member
The 'accept' code for untinker's quest should be something like the follows (has worked for me in my personal copy, but no guarantees):
Code:
 if (contains_text(visit_url("forestvillage.php?place=untinker"),"I lost my screwdriver somewhere"))
  visit_url("forestvillage.php?place=untinker&action=screwquest");

Also, the visit back to him after collecting the screwdriver needs to be in the forest village, not town.
 

Bale

Minion
After the recent update to zlib it seems as if eatdrink and farm both have decided to create all possible variables.
I'm trying to figure out why but I spent too much of last week in the ER and am still under the influence of mind altering prescription drugs.

I've been messing around with EatDrink lately so I'll tackle this one. It seems likely that the culprit is these lines here:

PHP:
if(to_boolean(vars["eatdrink_fav_" + replace_string(to_string(it)," ","_")]))

if(to_boolean(vars["eatdrink_daily_"+ replace_string(to_string(it)," ","_")]))

if(to_boolean(vars["eatdrink_avoid_"+replace_string(to_string(it)," ","_")]))

I assume the bug is clear, eh? I only wonder why nobody noticed a problem until recently. I fixed it by replacing it with this stuff:

PHP:
boolean var_check(string vari) {
	if(vars contains vari)
		return vars[vari].to_boolean();
	return false;
}

if(var_check("eatdrink_fav_" + replace_string(to_string(it)," ","_")))

if(var_check("eatdrink_daily_"+ replace_string(to_string(it)," ","_"))

if(var_check("eatdrink_avoid_"+replace_string(to_string(it)," ","_")))

I'm sorry that I cannot give line number or paste larger chunks of code, but my copy of EatDrink is growing different from yours.
 

Theraze

Active member
Second var_check is missing a ) at the end. In one of its two daily checks, it does skip the third ) because it's on an or-line, but the one directly following it needs it still.
 

Winterbay

Active member
I think the question is: What in the recent change to Zlib made it so that the orginal way to do it didn't create a lot of variables while the new one does?

Also, thanks for a potential fix but just to check: Where is "vars" defined?
 

Theraze

Active member
Vars is the whole set of zlib variables, right? This just checks to make certain that the variable is set before it returns it?

I'm guessing the 'change' is zarqon adding in type normalization. It makes certain that the value is initialized properly, but in so doing, checks that were a bit sloppy before are initializing variables left and right.
 

Winterbay

Active member
And is that defined every time you load a script that imports zlib? (I've not looked at zlib's functions at all so have no idea what they do or how).
 

Bale

Minion
Every time you import zlib it will use file_to_map() on your zlib variable file to fill out values for:
string [string] vars

Vars is the whole set of zlib variables, right? This just checks to make certain that the variable is set before it returns it?
Yes. If you reference a map for a variable, if that variable does not already exist, it will be created. Icky, eh?

I'm guessing the 'change' is zarqon adding in type normalization. It makes certain that the value is initialized properly, but in so doing, checks that were a bit sloppy before are initializing variables left and right.

That's unfortunate that he stopped checking for it. I never noticed since the first time I had such a problem.
 
Last edited:

Winterbay

Active member
Having done four exchanges according to the above mentioned code snippet my eatdrink now seems to have not created an abundance of variables and also runs. Thanks :)
 

slyz

Developer
Even if all those entries were created in the vars map, updatevars() is never called, so how did they end up in the vars data file? I don't think the normalization has anything to do with it either, since only setvar() calls normalized().

EDIT: oh I found it, setvar() is called in consumeone(), and that calls updatevars().
 
Last edited:

slyz

Developer
I don't think it's "unwanted", but if you don't know it works that way, it can have consequences you weren't expecting.

If you want to check if a map contains a specific entry, it is better practice to use contains or, in some cases, to go through all the existing entries by using foreach.
 

Winterbay

Active member
I don't think it's "unwanted", but if you don't know it works that way, it can have consequences you weren't expecting.

If you want to check if a map contains a specific entry, it is better practice to use contains or, in some cases, to go through all the existing entries by using foreach.

I think "consequences you aren't expecting" = "unwanted", but that's mainly semantics. I do agree that it's a bad idea to do it that way (especially with the consequences it gets) but it's also not an entirely unexpected way to try and do things.
 

fronobulax

Developer
Staff member
I assume the bug is clear, eh? I only wonder why nobody noticed a problem until recently
Even after you isolated it for me it took awhile. I blame it on prescription drugs. ...vars[x]... is going to create an entry for x if it is not already there and so the code creates an entry for almost every item, in the process of testing whether the item should be used, avoided or whatever.

In a perfect world, according to fronobulax, no user script would ever access vars directly. There would be a corresponding getvar that would be called. However, I won't suggest that as a zLib do so because it pretty much would force the creation of setvar and getvar pairs for each datatype in ASH and impose stronger typing and break other scripts in the process.

I will update EatDrink to eliminate this, ASAP but no promises as to when. Thanks for tracking this down, Bale.
 
I wonder if someone can help me clear up something with farm.ash. It seems like maybe I completely misunderstand how to use this script, because I finally got it to run without errors (had to comment about a line regarding the tavern) and it made me an amazing 2,000 meat in about 60 adventures. Basically here is what it decided to do:
1) Make and eat 3 purple pixel pies (for some reason getting to 9 fullness with pixel pies was the way to go)
2) Adventure at the thugnderdome for all my adventures
3) Mallsell a flange, autosell other stuff
4) Done, with a profit of about 340 meat plus the value of the flange

I get better results just running ascend.ash and letting it do the bounty and giant castle. What did I miss that people are able to run this script for over 100k meat per day? Can anyone please set me straight? I'm assuming I did something stupid.
 

Winterbay

Active member
I wonder if someone can help me clear up something with farm.ash. It seems like maybe I completely misunderstand how to use this script, because I finally got it to run without errors (had to comment about a line regarding the tavern) and it made me an amazing 2,000 meat in about 60 adventures. Basically here is what it decided to do:
1) Make and eat 3 purple pixel pies (for some reason getting to 9 fullness with pixel pies was the way to go)
2) Adventure at the thugnderdome for all my adventures
3) Mallsell a flange, autosell other stuff
4) Done, with a profit of about 340 meat plus the value of the flange

I get better results just running ascend.ash and letting it do the bounty and giant castle. What did I miss that people are able to run this script for over 100k meat per day? Can anyone please set me straight? I'm assuming I did something stupid.

A few questions:

1) What level are you?
2) Did it only eat to 9 fullness and stopped there, or had you already eaten some that day?
3) Do you have mall access and if so allow Mafia to buy things form the mall?
4) You can call the script with sim = true (or chose true in the pop-up if you just run the script) and see what it wants to do. If you try that and post the result that might help see what is happening.
 

Veracity

Developer
Staff member
I don't think it's "unwanted", but if you don't know it works that way, it can have consequences you weren't expecting.

If you want to check if a map contains a specific entry, it is better practice to use contains or, in some cases, to go through all the existing entries by using foreach.
I agree that if you want to check if a value is present you should use contains. However, it actually wouldn't be hard to change the code to not create the value if you read it and it has not been set. In textui/parsetree/CompositeReference.java:

Code:
	public Value getValue( final Interpreter interpreter )
	{
		interpreter.setLineAndFile( this.fileName, this.lineNumber );
		// Iterate through indices to final slice
		if ( this.getSlice( interpreter ) )
		{
			Value result = this.slice.aref( this.index, interpreter );

			if ( result == null )
			{
				result = this.slice.initialValue( this.index );
--->				this.slice.aset( this.index, result, interpreter );
			}
Delete that line. If you repeatedly reference the uninitialized value, we will repeatedly find null and will repeatedly cons up a new "initialValue" for the datatype, rather than saving it away. But, what the heck, if you ever actually set that entry, we'll throw away the initialValue anyway.
 
Thanks for the quick response.

A few questions:

1) What level are you?
2) Did it only eat to 9 fullness and stopped there, or had you already eaten some that day?
3) Do you have mall access and if so allow Mafia to buy things form the mall?
4) You can call the script with sim = true (or chose true in the pop-up if you just run the script) and see what it wants to do. If you try that and post the result that might help see what is happening.

1) Level 20
2) It ate to 9 and stopped, I had room for more
3) I have mall access, and to my knowledge I give Mafia mall access (it did put the flange in the mall)
4) I ate some food and ran the simulation. The summary is:
Best location is Thugnderdome with the command line 'maximize item drop;familiar Jumpsuited Hound Dog;{Peeled Eyeballs};'. Expected value is 835. The best monster there is Gnasty Gnome, who is worth 2334 meat.
Average meat from combats is 835
Average meat from noncombats (hardcoded) is 0
Combat rate is 100
Total of 6 monsters; meat per adventure is 835
Best monster is Gnasty Gnome, worth 2334.
 
Last edited:

Veracity

Developer
Staff member
The behavior Jason is referring to is in the "getSlice" method. That iterates down the dimensions of a map, creating intermediate levels as needed. The method I pointed you to is used to fetch a value in the final level, after getSlice has been used to get there.

Edit: here's a little test program.

Code:
int [int,int] test;

print( "test contains 1 = " + test contains 1 );
print( "test[1] contains 2 = " + test[1] contains 2 );
print( "test contains 1 = " + test contains 1 );
print( "test[1,2] = " + test[1,2] );
print( "test contains 1 = " + test contains 1 );
print( "test[1] contains 2 = " + test[1] contains 2 );

foreach key1, slice1 in test
{
  print( "test[" + key1 + "] = " + slice1 );
  foreach key2, value in test[ key1 ]
  {
    print( "test[" + key1 + "," + key2 + "] = " + value );
  }
}
and here's how it operates with the current code:

> mmaps

test contains 1 = false
test[1] contains 2 = false
test contains 1 = true
test[1,2] = 0
test contains 1 = true
test[1] contains 2 = true
test[1] = 2
test[1,2] = 0
Notice that as soon as we referenced test[1], that slice was created. When we referenced test[1,2], the second slice was created. And iterating over the multi-dimensional map at the end, we see that test[1] has index 2 in it, and test[1,2] has value 0 in it.

I removed the line from getValue() as I suggested, compiled, and reran the test.

> mmaps

test contains 1 = false
test[1] contains 2 = false
test contains 1 = false
test[1,2] = 0
test contains 1 = true
test[1] contains 2 = false
Notice that referencing test did NOT create that index. Referencing test[1,2] found the default value and did create the intermediate layer test[1] but did not create element test[1,2].

Edit 2: I changed the foreach loop at the end:

Code:
foreach key1 in test
{
  print( "test[" + key1 + "] = " + test [key1] );
  foreach key2 in test[ key1 ]
  {
    print( "test[" + key1 + "," + key2 + "] = " + test[key1,key2] );
  }
}

and reran it:

> mmaps

test contains 1 = false
test[1] contains 2 = false
test contains 1 = false
test[1,2] = 0
test contains 1 = true
test[1] contains 2 = false
test[1] = aggregate int [int]

Now you can see if intermediate layer there at test[1]. It's empty, since when we foreach over it we find nothing.

Edit n: OK, last demo. I modify the test program thus:

Code:
int [int,int] test;

void pmap()
{
  foreach key1 in test
  {
    print( "test[" + key1 + "] = " + test[key1] );
    foreach key2 in test[ key1 ]
    {
      print( "test[" + key1 + "," + key2 + "] = " + test[key1,key2] );
    }
  }
}

print( "test contains 1 = " + test contains 1 );
print( "test[1] contains 2 = " + test[1] contains 2 );
print( "test contains 1 = " + test contains 1 );
print( "test[1,2] = " + test[1,2] );
print( "test contains 1 = " + test contains 1 );
print( "test[1] contains 2 = " + test[1] contains 2 );
pmap();
test[1,2] = 3;
print( "test contains 1 = " + test contains 1 );
print( "test[1] contains 2 = " + test[1] contains 2 );
pmap();
and get this:

> mmaps

test contains 1 = false
test[1] contains 2 = false
test contains 1 = false
test[1,2] = 0
test contains 1 = true
test[1] contains 2 = false
test[1] = aggregate int [int]
test contains 1 = true
test[1] contains 2 = true
test[1] = aggregate int [int]
test[1,2] = 3
...which looks reasonable to me.
 
Last edited:
Top