ascend_HC.ash (Work in Progress)

Oh. Multiplies it by 4! Somehow I was wrong. Then A gets a frequency of 66% while the other two get 17% each. Damn that's powerful!
 
Olfaction, while not straightforward, isn't too hard to figure out from the Wiki. What I need to educate myself about is combat frequency. If someone is running +10% combats in a zone with 8 combats and 2 noncombats, what is their chance of encountering a combat? Is it additive (90%) or multiplicative (88%)?
 
Additive, but number of non-combats and combats is irrelevant.

Each zone has a combat frequency which has nothing to do with the comparative quantity of combats and noncombats. Add the +10% to that.

e.g., the combat frequency in Sonofabeach is 10%. 10+10 = 20% combats.
 
Last edited:
So for zones with noncombats, a combat will occur

minmax((combats + 3*trailedmonsterexistsinzone) / noncombats + combat_rate_modifier(), 0, 1.0)

of the time?

I'd still have to figure out the math for the chance that you would encounter monster X in a particular zone. I wrote up a semi-quick formula but realized it was erroneously based on monsters being evenly distributed.

In the meantime, back on topic:

StDoodle, you've mentioned that certain of the quest/adventuring scripts published here are more casual -- they get the job done, but not optimally. As I understand it, this is one of the primary motivations for your project. If any of my scripts match that description, I'd appreciate your feedback on how they might be optimized. My playstyle is rather casual (I don't have time to play optimally), so I may not think of things while scripting that an optimized player would want the script to consider. I think it might be easier to optimize something casual than write something optimal from scratch, especially since many of these scripts have already gone through a fair amount of testing/debugging.
 
First, I should mention that it's looking like I'm going to be busy for longer than expected. So this project as a whole is on a rather indefinite hold.

The goal -- once I get back to working on it -- is to come up with a framework of information tracking and break various tasks down into the smallest possible chunks, such that they can be reordered and optimized by others more easily. I'd like to come up with something that allows for other scripters to be able to plug-and-play using my scripts, without having to write most of the actual adventuring & quest-progress-checking. I don't intend to make a very "optimal" overall script myself; I'm hoping to come up with enough of the groundwork that better players than myself feel comfortable organizing what gets done & when. That's the goal, anyway. ;)
 
You might want to have a look at this post by Stupac in the KoL G-D forum.

Removing superlikelies, clover adventures and other special cases, the game:

1) first decides if you are going to have a combat or a noncombat.
For a zone with a base combat rate of 60%, you have a minmax((60 + combat_rate_modifier())/100.0, 0, 1.0) chance of getting a combat. Of course, it can be a little more complicated when you have skippable noncombats.

2) then decides which monster or which noncombat you will encounter, where monster appearance rate can be modified by Olfaction or by banishing (and where some zones already contain more than 1 occurrence of a specific monster).

Without considering special cases, the chance of encountering a specific monster will be:
combat_encounter_rate * number_of_occurrences_of_monster/total_number_of_occurrences

That would give you a straight-up average (or whatever it's called in stats), but calculating the variance would be a lot more difficult because it would require taking into account interaction with the queue.
 
Last edited:
No. Relative numbers of combats and non-combats are irrelevant. It isn't changed by olfaction. First KoL rolls to see if there is a combat or noncombat. Then it rolls to see which encounter you get of that type. Combat rate is simply this:

PHP:
float combat_rate(location whereto) {
   float [monster] temp = appearance_rates(whereto);
   return minmax(temp[$monster[none]] + combat_rate_modifier(), 0.0, 100.0)
}

Edit: It seems that slyz ninjaed me nicely, but I provided the function. :D
 
Ah, that simplifies matters a great deal. I'd been thinking it would be rather tricksy due to Olfaction altering all percentages but combat rate modifier altering one percentage individually, and the others as a group. But this is much simpler. I should be able to add that in fairly quickly.

@Doodle: I've been thinking a lot about algorithms for sorting and optimally ordering possibilities (for some reason...), so in case you're interested, here's how I would script it. It's basically identical to my approach to BatMan -- get all the information available, remove unavailable possibilities, then reduce your remaining possibilities to a single number, sort, and perform the top action. Then repeat.

First, start with the basic idea of my Hardcore Checklist script. All of the actions are in an external data file on the Map Manager which can be expanded and tweaked by anyone. Each action contains, at minimum, the condition that must be true, and what to do if it's not. Presently, it handles:

  • Adventuring somewhere until certain text appears on a certain page
  • Adventuring somewhere to get N of a lacking item, unless
    - certain text is on a certain page
    - you have a certain other item
    - you have a certain familiar
    - you have disabled the item's quest stream
  • Yeah, it has options to include a few optional quest streams (i.e. getting a maid, or pre-farming NS tower items), but your script should not hard-code the streams but allow for unlimited streams (covered below).

However, there's plenty that it lacks to be a complete ascension script (it doesn't unlock anything or make anything or use much of anything), or an optimized script. An optimal script should be able to weigh various options (i.e. optimize its actions). Checklist is entirely without decision-making abilities -- it's just a list, in order, of actions to do.

I envision something way cooler for this script. After an action is completed/verified (which could be acquiring an item, unlocking a quest, achieving a certain level, calling a script/function... -- this would all be in the data file -- I actually overloaded the data file format fairly cleverly in Checklist which is why I recommended it as a starting point), the script will rebuild the list of possible actions and perform the most optimal one. This is exactly what BatMan does to calculate combat options; since any number of things could have changed after completing an action, it recalculates (including rebuilding the list of possible actions) after every action.

How would your script build the list? Well, first, you'd painstakingly make a data file containing a list of very specific actions that need doing, akin to Checklist's data file but much more anal, and with three important structural changes: 1) eliminate the safemox field, since ZLib makes that information available quite accurately these days, 2) add a 'stream' field, and 3) add a 'prereq' field. The stream field would contain which quest stream(s) the action belongs to. All actions mandatory for ascension would be one such stream. Another would be a maid. Another (several, actually) would be the Nemesis quest. Another might be a Pagoda. Another would be the White Citadel quest. Another would be pre-farming NS tower items (these should be included in the main stream if you can identify them using your 'scope). You could even include the gnomish neverending NPC quest. But non-mandatory streams could be added in after the main stream was finished, and it wouldn't even be much of a hassle to add since they wouldn't need to be in order.

Why no order? Because the prereq field would simply point to which step must be completed before that action is available. The way I see it, almost every action will have a prereq. So when building the list of available options, if the prerequisite step had not yet been completed, the script would not add that action to the list of possible actions to consider (or, if the action cost nothing, it would just perform it automatically). This means that you would have an action "achieve level N" for every level, and then all of the steps that depend on that level being reached would include that as a prereq -- or they would chain off from there. Bonus: nearly all the hassle about whether you can or can't adventure somewhere would be part of the data file, rather than the script. Another bonus: the action list doesn't need to be in any specific order!

So now, you've built a list in memory of all actually possible actions that have not yet been done for the quest streams which your user has selected (somehow). Now to sort them based on turncount! Turn cost vs. turn profit.

The cost is easy -- once has_goal() accounts for Olfaction/frequency/item-yielding noncombats, you'll be able to pretty accurately predict the number of turns everything will take, and without too much difficulty. Don't include meat cost! Achieving the necessary meat for an action could be a prerequisite action, but don't include the meat as part of the cost, since all actions are necessary to complete your chosen streams, no matter what they cost.

The gain is the hard part to calculate. Stat gain is a big deal, but not for the obvious reason. The only thing it's good for is unlocking things, so it's not really a factor unless you can unlock things that give you more turns! (This is counterintuitive but true, since you have narrowed the field to only necessary actions which you will have to perform at some point.) The hardest part of this calculation will be figuring out whether going up a level would let you eat/drink something that gives you far more adventures than you could eat/drink otherwise. I'm not sure if EatDrink has any speculative abilities built-in, but if so, that would be excellent for this purpose -- compare your predicted food/drink gains at your present level to the predicted gains at the next level and then decide if achieving the next level is possible before eating/drinking. Huge chore, that, and in the meantime you may want to take a "run the actionsorter till only a handful of advs remain; call eatdrink; run the actionsorter again" approach.

After stat gain, there is item gain -- which again, usually counts for nothing except for items that gain you turns. Basically, consider food/item drops to be turns gained, although probably not at a 1:1 ratio. I'd probably add a special action to the list of available actions each iteration -- groceryshop. Basically, for each available zone that drops food/drink, what is the average turn gain per turn spent? Take the best of those, then figure out if turns gained >= turns spent + turns gainable from your current inventory.

After that, most actions won't gain you turns, so you should simply choose the action that gives you the smallest stat gain, since at that point you will actually be getting the largest percent of a level that you will ever get for it.

To sum up, this is the process that the actionsorter would perform after completing every action: iterate through the master list and remove actions already completed, perform free actions (from any stream!), remove actions from unselected quest streams, and remove actions that have unsatisfied prerequisite actions, in that order. Add a consumables-farming action to the list if appropriate. From the remaining actions, perform the highest turn-gaining action (food/drink earners, basically, possibly including leveling), or failing that, the lowest stat-gaining action. Rinse, repeat.

That's the angle I'd come from! :) Hopefully that gives you some food for thought if nothing else!

-----

tl;dr: Everyone! You can buy your own submarine!
 
Let's make this list, most of the code to do individual tasks is sitting around on the forum somewhere. We can split it up into manageable chunks, this is too much work for a single person anyway.
 
Last edited:
Perhaps once the action format is decided, people could claim and then post individual levels/quests, with the proper prereq's all in place. Plug 'n' play!
 
Perhaps...

PHP:
// Various functions made by people would go here.
string[string] decide() {
    // Decide to do stuff here. Return a function to call, and its parameters.
    // Index would be the function, according to this rough template. 
}
void main() {
    while(true) {
        string[string] temp = decide();
        foreach s in temp
            call s(temp[s]);
        // Note that we'd get out of this infinite loop by having decide() return 
        // "abort" (parameter being something like "Turn rundown completed!")
        // at some point, since "exit" doesn't work with call. A bit sloppy, I know.
        // Unless, of course, you want to work in something for 
    }
}
 
I would like to see things that can be done for whatever goal the script is going for: for example, I would like to use my llama for 2 gongs, then my sandworm for 2 aguas (if I'm doing something that allows me to use a stat familiar).

This wouldn't be in the master list of things to be done, but would be considered once the goal is decided, and the script starts deciding what to do exactly to reach it.

As goals, I would see: reach a stat (or level), get specific items, kill a specific monster, or get a noncombat adventure. Once the goal is decided, either by following a sort of user-scripted list or by making real decisions, a set of buffs to run, a familiar to use, and a combat strategy are decided and the script can finally adventure.

With all this, a 'meat per adventure' total can be computed, with the cost of MP and the expected output of combats (how much MP/HP was spent, meat lost/won), and the set of buffs and/or combat strategy can be derived.
 
The idea of including familiar-item farming (and using, in the case of gongs/absinthe, etc) is excellent, particularly since it usually gains turns. Ideally it would be sensitive to both familiar type and the is_100_run setting. For example, if a goal isestimated to take more than 6 turns to complete, the script could use an absinthe beforehand (and trust a counterScript to handle the !pipe farming).

An important goal type would be to visit a page in search of specific text, which would often be used as a prerequisite. There may also need to be handling for calling internal ASH functions, in case we come across something that can't be performed as one of the predefined actions.
 
Back
Top