CanAdv -- check whether you can adventure at a given location

matt.chugg

Moderator
zarqon said:
1) I love the equipcheck() idea. Added that in, along with outfitcheck(). These will only swap gear if prep is true.

Excellent!

zarqon said:
2) For boss zones, often the link to the boss area changes depending on whether the boss is defeated, so detecting whether the area is open and the boss remains undefeated should usually be doable in a single server hit.

I'm currently on day 2 of an ascension, but forgot to check again the boss bat and goblin king yesterday, I will however try and remember to check any bosses I encounter today.

3) Bat zones definitely need special handling for the use of sonars. I think the script ought to attempt to use enough sonars to reveal the desired zone, regardless of prep. If done right, the detection for that could be done in a single server hit. The question now becomes how to script that efficiently. For now, I added this after all three sonar-only bat zones, which I think is fairly nice:

Code:
if (!levelcheck(4)) return false;
string bathole = visit_url("bathole.php");
int sonarsneeded = to_int(!contains_text(bathole,"batratroom.gif")) +
to_int(!contains_text(bathole,"batbeanroom.gif")) + to_int(!contains_text(bathole,"batbossroom.gif"));
if (sonarsneeded > 0) {
   use_upto(sonarsneeded,$item[sonar-in-a-biscuit],true);
   bathole = visit_url("bathole.php");
}
return (contains_text(bathole,substring(to_url(where),0,index_of(to_url(where),"&"))));

Note that this will detect whether the Boss Bat has been defeated.

Also note that this uses a function from ZLib. Since this script also needed to use resist(), I simply made it require ZLib. Scripts that want to use both ZLib and CanAdv can now just import CanAdv.

Nice, thats looks very elegant and handles all of the all of the bats very nicely, I guess its true what they say about you and bats!

That's a good thought, but the existing operators already work that way.

....

I asked about this long ago and was happy to discover that ASH behaves this way. I take advantage of it all the time in my scripts.

Thats really excellent, I had no idea that mafia handled this in this manner!


Now, if only use() had a useful return value...

Unfortunatly I have nothing to help you there :p
 

Bale

Minion
We should petition Veracity to get a useful return value from use().

By "petition" I mean "ask nicely". I do not mean to collect signatures in an overbearing manner.
 

slyz

Developer
I started testing out the bounty.ash script, with the 'smallest' choice, and it chose the hippy bounty even though the hippy camp is bombed back to the stone age for me. I just browsed canadv.ash quickly, but it doesn't seem to check if the hippy camp is still available.

Edit: I removed the very wrong fix.

I don't know how to check the the war is in progress, so I don't know how to implement this, but we should check:

have dinghy & war not started
OR
war done and side X defeated

I'll take another look in other threads when I have more time.
 
Last edited:

StormCrow42

Member
Just as a note, but the Fernswarthy's Ruins detection isn't working correctly, I'm not certain when you lose the key, but none of my aftercore characters have it and they've all opened up the ruins.

Also, I think I recall it not detecting the Pirate's cove properly.
 

dj_d

Member
I haven't tested it much, but the attached canadv should detect when the hippy camp is unavailable because you finished the war - preventing bounty.ash from getting stuck because it takes a bounty that you are unable to complete.
 

Attachments

  • canadv.ash
    18.6 KB · Views: 108

cakyrespa

Member
I'm working on a version of LevelUp, mainly to see if I can do something interesting with it. However, I found out if I spam can_adv() to find suitable area, I got some side effects I wasn't really planing for.

Code:
   boolean itemcheck(item req) {
      if (available_amount(req) == 0 && (!prep || !retrieve_item(1,req))) {
         print("You need a '"+req+"' to adventure here.","red"); return false;
      } return true;
   }

The above basically doesn't try to acquire the item if the prep flag is set to false. Likewise, I don't think we should use the enchanted bean if prep is not set to true.

Code:
case $location[Fantasy Airship]: return (levelcheck(10) && (visit_url("plains.php").contains_text("beanstalk.gif") || (prep && use(1,$item[enchanted bean]))));

The other idea is a bit simpler. When I'm working on the leveling, I'm using a lot of can_adv() calls mainly to see which areas are an option. This causes a fair number of server hits for basically just investigating the options. I got it to significantly reduce the number of hits with a short-term cache of the url visiting. Obviously, this could work in zlib just as well as can_adv, but it seems to help with my script.

Code:
string[string] url_contents;
int[string] url_last_check;

string visit_url(string url, int time) {
   int last_checked = to_int(url_last_check[url]);

   if (my_turncount() > last_checked) {
     string url_content = visit_url(url);
     url_contents[url] = url_content;
     url_last_check[url] = my_turncount() + time;
     return url_content;
   }

   return url_contents[url];
}

boolean url_contains(string url, string contents) {
   return visit_url(url).contains_text(contents);
}

boolean url_contains(string url, string contents, int time) {
   return visit_url(url, time).contains_text(contents);
}

Then, it is just a matter of changing the contains_text(visit_url(""), "") and visit_url("").contains_text("") calls to use url_contains("", "", 10). Those functions are pretty self-contains, so they might be a possible addition to zlib. The idea behind it is once you open up the "Beanbat Chamber", it isn't going to close again for this ascension. So, why not check just once? Ditto for airship and most of the unlockable areas that require visit_url().

EDIT: Forgot one:

Code:
if (sonarsneeded > 0 && prep) { use_upto(sonarsneeded,$item[sonar-in-a-biscuit],true); bathole = visit_url("bathole.php"); }

EDIT: Thing I screwed up the logic on that first one. *sigh*
 
Last edited:

cakyrespa

Member
Just a few more minor things dealing with "prep".

Code:
boolean checkguild(boolean prep) {                            // guild quest-unlocking
   if (prep) cli_execute("guild");
   item my_lew() {
      switch (my_class()) {
         case $class[seal clubber]: return $item[hammer of smiting];
         case $class[turtle tamer]: return $item[chelonian morningstar];
         case $class[pastamancer]: return $item[greek pasta of peril];
         case $class[sauceror]: return $item[17-alarm saucepan];
         case $class[disco bandit]: return $item[shagadelic disco banjo];
         case $class[accordion thief]: return $item[squeezebox of the ages];
      }

      return $item[none];
   }

   if (prep && !white_citadel_available()) visit_url("guild.php?place=paco");
   if (prep && item_amount($item[fernswarthy's key]) == 0) visit_url("guild.php?place=ocg");
   if (prep && item_amount(my_lew()) + equipped_amount(my_lew()) == 0) visit_url("guild.php?place=scg");
   return true;
}

And then change calls from "checkguild()" to "checkguild(prep)". This cuts down on the server hits when calling a large number of can_adv() from a single script. Between this and the cache, I think I've got the number of visit_url() calls from 24 to 10 if you go through most of the locations (I skip a lot because I'm avoiding island war, clan, and holiday locations).

Not absolutely sure about the cli_execute("guild"), but I figured it was safe to check prep on that one.

Code:
   case $location[Dark Neck of the Woods]:
   case $location[Dark Heart of the Woods]:
   case $location[Dark Elbow of the Woods]: return (levelcheck(6) && !have_skill($skill[liver of steel]) && !have_skill($skill[stomach of steel]) && !have_skill($skill[spleen of steel]) && !contains_text(visit_url("quests.php?which=2"),"cleansed the taint"));

I noticed in the Dark * of the Wood adventures, it only checked for spleen of skill. The above block adds it in an attempt to avoid hitting the server. I think we could also check for the items, but I didn't.

I did notice something strange. visit_url("quests.php?which=2") were returning a blank string. When I looked at the client, I noticed it was "questlog.php?which=2". Any idea if I'm doing something wrong to cause quests.php not to work?

Code:
   case $location[Greater-Than Sign]: return (primecheck(44) && !url_contains("dungeons.php", "The Dungeons of Doom"));
   case $location[Dungeons of Doom]: return (primecheck(44) && url_contains("dungeons.php", "The Dungeons of Doom"));

For the Dungeon of doom verses Greater-Than Sign, the above code uses a visit_url() to figure out which one is available. Might help with bounty.ash since I've gotten burned before when I forgot to unlock the Dungeon of Doom.
 

dj_d

Member
I'm finally getting around to using canadv in some code! I'm calling it a bunch of times, and it's very chatty. It'd be good to have a silent mode where it doesn't print() the result of the function call. Perhaps a verbose flag, or only print results when it's called directly via main().
 

dj_d

Member
Another thing - I think it'd be good to take the approach First Do No Harm. As is, it actually tries to *do* some stuff, like open the guild - that could be bad if, for example, you're a rank noob trying to figure out if you have access to the guild yet. I'd like to see all adventure-using, item-consuming, outfit-wearing, or other actions that could actually modify account state be turnable offable with a flag.

Oh - and I may have an out of date version, but there's two strings missing in my version from the F'c'le that make mafia crash when you call canadv there.

ed: oh sheesh - it's burning sonar biscuits too!
 

cakyrespa

Member
Another thing - I think it'd be good to take the approach First Do No Harm. As is, it actually tries to *do* some stuff, like open the guild - that could be bad if, for example, you're a rank noob trying to figure out if you have access to the guild yet. I'd like to see all adventure-using, item-consuming, outfit-wearing, or other actions that could actually modify account state be turnable offable with a flag.

ed: oh sheesh - it's burning sonar biscuits too!

I think that is what the `prep` flag is suppose to do. At least, that's the assumption I was making when I posted the modifications a few posts back. Mainly because my level-up script ends up hitting can_adv() fairly often just to figure out what places are viable choices.
 

dj_d

Member
Another missing bit - it doesn't seem to handle Fernswarthy's Tower (another case where you can get an unfillable bounty).
 

zarqon

Well-known member
I'm a bit disappointed with much of the recent feedback. 19 comments since the last update, and only three actually contributed to the project as per my requested guidelines.

@Sputnik: Thanks for reporting the missing vacation area. I've added those in to my personal copy, so whenever I get to making the next update, all three vacations will be included.

@cakyrespa: Thanks for submitting code to the project. I have made most of the changes you submitted, although I didn't change the bit with the sonars, because if you're checking can_adv(beanbat chamber) and you have enough sonars, the function should return true. I wrote much earlier about the decision to always use sonars if needed, since everyone always has to do that in order to ascend. I am OK with making that contingent on prep, but then we will need a different algorithm that counts how many more sonars are needed to access the specified zone.

As for all the other reported issues -- I clearly explained in the first post that this was an incomplete alpha release, with many problems and missing zones. I envisioned a community coding effort, with lots of code blocks being posted and lots of people learning ASH, not an everyone-report-bugs-to-Zarqon spree. I already know there are problems. I told you up front there are problems, and requested community help in fixing them, not just identifying them. I didn't finish this script before release because I wanted people to learn ASH scripting by finishing it together.

Sorry I sound whiny here, but I'm really in a bit of a funk about this. I expected one thing and got another. I kind of want to delete the script and go home and play by myself.

Another update will come eventually. When I stop feeling so whiny.
 
It's telling me that Drunken Stupor and St. Sneaky Pete's Day Stupor are missing locations, thought it looks like there's some code that's supposed to handle them:

Code:
// check drunk-only locations before doing drunkenness check
if (my_location() == $location[St. Sneaky Pete's Day Stupor]) return (my_inebriety() > inebriety_limit() && contains_text(visit_url("main.php"),"St. Sneaky Pete's Day"));
if (my_location() == $location[Drunken Stupor]) return (my_inebriety() > inebriety_limit());

It just looks like a small typo, should probably be where instead of my_location()

Code:
// check drunk-only locations before doing drunkenness check
if (where == $location[St. Sneaky Pete's Day Stupor]) return (my_inebriety() > inebriety_limit() && contains_text(visit_url("main.php"),"St. Sneaky Pete's Day"));
if (where == $location[Drunken Stupor]) return (my_inebriety() > inebriety_limit());

I believe the Fernswarthy's Ruins problem can be fixed by changing the item check from the key to the letter

Code:
case $location[Fernswarthy's Ruins]: return (itemcheck($item[Fernswarthy's letter]));
 
Last edited:

cakyrespa

Member
@cakyrespa: Thanks for submitting code to the project. I have made most of the changes you submitted, although I didn't change the bit with the sonars, because if you're checking can_adv(beanbat chamber) and you have enough sonars, the function should return true. I wrote much earlier about the decision to always use sonars if needed, since everyone always has to do that in order to ascend. I am OK with making that contingent on prep, but then we will need a different algorithm that counts how many more sonars are needed to access the specified zone.

I think in code. :)

Do you really need to count the sonars? If prep is false, I would expect it to return true if the area is already open and false if it is not. Yeah, it isn't as useful for the obvious reasons, but I would expect semi-automated approaches to open it there (!canadv(beanbat) && have_item(sonars))... etc. Having canadv(prep = false), simply tell you "yes, it is open", may be sufficient (and what I'd like to see). Now, if prep == true, then I say go for it.
 
Top