Feature Tracking zone types for the Cold Medicine Cabinet

Captain Scotch

New member
Hey folks.

It would be really lovely to have internal Mafia support for tracking the zone typing of a user's last 20 combats for the Cold Medicine Cabinet. If you are unfamiliar with the mechanic, it works like this: the eligible spleen item you can get from the Cold Medicine Cabinet is based on the zone types you've visited over your last 20 turn-taking combats; whichever zone type out of Underground, Indoors, and Outdoors makes up at least an 11/20 majority will spawn the corresponding spleen item. When doing speed runs, I have traditionally tried to keep the zone status straight on a piece of paper, and it's (frankly) relatively difficult; it adds a lot of time to my runs. I tried to make a postcombat script and found it was relatively difficult to do, and abandoned it.

In order for mafia to support this, I think the spec for it would be a new preference like "lastTwentyCombats" where each character represents the type of zone encountered in that combat in the last 20. It could start out every new ascension as "XXXXXXXXXXXXXXXXXXXX" (twenty Xs) to represent that there are 20 zoneless combats in the CMC queue. As you adventure, it could cycle out the last character and add U, I, or O, only altering the preference on combats that did not return FREEFREEFREE upon completion, reflecting the zone type of the zone the monster was placed in. Note that for the purposes of the CMC, free combats do not count, so it has to be turn-taking. And noncombats do not impact the proceedings at all, except (possibly) in a weird case we need to re-spade that I will footnote below.

So, for a hopefully clearer example, let's say that I ascended a new character and spent:

- 5 turns in the Spookyraven Kitchen (an indoor zone)
- Used Clara's Bell to get one NC in the Dark Heart of the Woods (an outdoor zone)
- Fought a free Kramco in the sea (zoneless; sea is "X" for the purposes of this tracking)
- 2 turns in Guano Junction (underground)

In this example, the property would update within the first and last bullet, and would not change at all in the second two bullets (as one is an NC and the other is a free fight). Therefore, after these 8 turns (and 1 free fight), instead of "XXXXXXXXXXXXXXXXXXXX", the string would instead be "UUIIIIIXXXXXXXXXXXXX", reflecting the new U/I turns.

I'm not positive that this is an easy feature to store or implement, and I expect that as it is built out, issues will be found with how KOL is actually registering CMC zones; earlier today we went over some of the spading and it sounded as though there were some residual oddities remaining from the old behavior (namely, that zoneless combats when flowed into NCs that do not take turns actually are somewhat inexplicably being overriden in location by the location in those free NCs; this is behavior that replicates old behavior prior to a major mechanical change to the IOTM that occurred in January, but it sounded as thought TPTB had fixed the old behavior, so if it still works like this, it definitely could make tracking a huge pain)... but even just a simple version of this would be massively helpful both for spading how it is currently working and assisting speedrunners in their on-the-fly routing.

I am OK at TS and Ash, but have never really touched Java, so I am a bit nervous about trying to put together this PR myself and would prefer if at all possible for someone else to at least take a first crack at it... but I am happy to answer any questions about the known mechanics of the CMC and any thoughts on how this could help players! :) Thank you all for reading!

-- Captain Scotch
 
How does this mechanic interact with:
- Backing up, macrometeor, CLEESH, and other monster replacers
- Lecture on Relativity
- Fights that are free for weird reasons
- Using the Force to end a combat
?

It would be nice to get some more spading in for how this interacts with zoneless encounters as well; that sounds like the hardest part of this to handle.
 

Captain Scotch

New member
How does this mechanic interact with:
- Backing up, macrometeor, CLEESH, and other monster replacers
- Lecture on Relativity
- Fights that are free for weird reasons
- Using the Force to end a combat
?

It would be nice to get some more spading in for how this interacts with zoneless encounters as well; that sounds like the hardest part of this to handle.
In order:
  • Backups do not notably influence this mechanic. If you backed up a free fight, it will not count; if it took a turn, it will. The zone is simply assigned based on the original monster you replaced.
  • Same with CLEESH, replace monster, and macrometeor.
  • I have not tested with professor since the mechanics change. Prior to the mechanics change, there was some spaghetti there, so would not be surprised if there's some zoneless nonsense with the professor.
  • While this is not exhaustive, so far, none of the "weird" free fights I have tested have seemed to impact spleen item selection. Things I have tested (though not exhaustively) include machete-freekilled dense lianas, Breathitin fights, and Drunk Pygmies freekilled with Bowls of Scorpions.
  • Using the Force with the cosplay saber does not impact CMC selection.
Here are two other mechanical notes I forgot to mention in my already-way-too-long first post.
  1. Once you select your 5th item for the day, the preference should remain frozen until the next day; the CMC completely ceases tracking after you have selected your 5th item of the day.
  2. I have not properly tested this, but I believe that if you change worksheds into the CMC, it is effectively the same as starting a new ascension with it regardless of what you did before swapping to the CMC. This should be pretty easy to test for me soon.
Thanks for pointing out some specific situations that warranted explaining. :)
 

Ryo_Sangnoir

Developer
Staff member
Do combats that you lost update the tracking?

Do combats that would have been free, but that you lost (and therefore cost a turn) update the tracking?
 

Erosion

Member
I would like for the pref to update from the right side, for consistency with all other queue-ish prefs in mafia (combat queue, cleaver queue, etc)
XXXXXXXXXXXXXIIIIIUU instead of UUIIIIIXXXXXXXXXXXXX.
  1. I have not properly tested this, but I believe that if you change worksheds into the CMC, it is effectively the same as starting a new ascension with it regardless of what you did before swapping to the CMC. This should be pretty easy to test for me soon.
This is untrue, CMC will track zones even when it is not your active workshed. If you're using garbo Mayo/Asdon and swap into CMC, you will be able to get an (indoor zone) extrov on demand.
Do combats that you lost update the tracking?

Do combats that would have been free, but that you lost (and therefore cost a turn) update the tracking?
adv.php combats that are lost or run away from will indeed affect CMC tracking.
It would be nice to get some more spading in for how this interacts with zoneless encounters as well; that sounds like the hardest part of this to handle.
Zoneless combats will run down the 20-adv consultation cooldown but do not seem to affect medicine zone tracking (ie they have the same influence as any noncombat). However, underwater combats count towards Fleshazole (X).
 

lostcalpolydude

Developer
Staff member
And there will need to be another symbol for adventure.php locations that don't yet have an environment type (new content that isn't in the data files yet).
 

gausie

D̰͕̝͚̤̥̙̐̇̑͗̒e͍͔͎͈͔ͥ̉̔̅́̈l̠̪̜͓̲ͧ̍̈́͛v̻̾ͤe͗̃ͥ̐̊ͬp̔͒ͪ
Staff member
So something like this?


I'll write tests imitating the example and expected outcome of what scotch posted above in due course.

This also does left newest right oldest but we can easy swap that
 

Erosion

Member
I assume this doesn't include free runaways, but I wouldn't know.

What about "free" underwater combats without fishy?
CMC zone progress is only tracked for turn-taking advs. I would assume that unfishy free runs used underwater count as 1x underwater and underwater (2) adventures count as 2x underwater, both of which would be counting for Fleshazole.
 

gausie

D̰͕̝͚̤̥̙̐̇̑͗̒e͍͔͎͈͔ͥ̉̔̅́̈l̠̪̜͓̲ͧ̍̈́͛v̻̾ͤe͗̃ͥ̐̊ͬp̔͒ͪ
Staff member
Basic support for this has landed, and you can run `cmc` to see what your expected pill is. I want to expand on the information in that readout when I have time. I imagine it will occasionally be wrong as we iron out combats that should be excluded.
 

gausie

D̰͕̝͚̤̥̙̐̇̑͗̒e͍͔͎͈͔ͥ̉̔̅́̈l̠̪̜͓̲ͧ̍̈́͛v̻̾ͤe͗̃ͥ̐̊ͬp̔͒ͪ
Staff member
Ok as I flesh out the further support, I realise the ash function I added is probably not quite right - it might be nicer to have

Java:
item [int] expected_cold_medicine_cabinet();

where the int key is the choice and the item is the item you'd get from that choice. That is once we have estimation in place for all the different items. Or I suppose I can keep some of them as constantly $item[none] for now. So don't start using that function all over your code just yet, I reserve the right to change it :p
 
If there are other reasons to track lastCombatEnvironments then the last environments for Cold Medicine Cabinet can not be tracked in the same lastCombatEnvironments preference because it seems Cold Medicine Cabinet stops tracking after it is used the 5th time in a day and at the beginning of the next day uses the last environments it tracked, not the last environments at the end of the previous day

lastCombatEnvironments skips tracking one type of cellar.php encounter I think correctly, and records another type as ?, I think incorrectly. One category is noncombats like "Those Who Came Before You" and "Of Course!" and it is probably skipping those, the other category is the combats like "bunch of drunken rats", these combats in cellar.php are probably not tracked by the Cold Medicine Cabinet
 
Last edited:

gausie

D̰͕̝͚̤̥̙̐̇̑͗̒e͍͔͎͈͔ͥ̉̔̅́̈l̠̪̜͓̲ͧ̍̈́͛v̻̾ͤe͗̃ͥ̐̊ͬp̔͒ͪ
Staff member
If there are other reasons to track lastCombatEnvironments then the last environments for Cold Medicine Cabinet can not be tracked in the same lastCombatEnvironments preference because it seems Cold Medicine Cabinet stops tracking after it is used the 5th time in a day and at the beginning of the next day uses the last environments it tracked, not the last environments at the end of the previous day
I had to read this quite a few times to understand it but are you saying that the environments stop being checked after the last consult? If so that's annoying because I've probably named this pref too widely.
lastCombatEnvironments skips tracking one type of cellar.php encounter I think correctly, and records another type as ?, I think incorrectly. One category is noncombats like "Those Who Came Before You" and "Of Course!" and it is probably skipping those, the other category is the combats like "bunch of drunken rats", these combats in cellar.php are probably not tracked by the Cold Medicine Cabinet
Noncombats are not tracked by design. The cellar is an odd one - what should it be tracked as? Needs spading. In the data files we have

Woods cellar=0 Env: none Stat: 0 Level: 6 The Typical Tavern Cellar
 

Erosion

Member
I had to read this quite a few times to understand it but are you saying that the environments stop being checked after the last consult? If so that's annoying because I've probably named this pref too widely.

Noncombats are not tracked by design. The cellar is an odd one - what should it be tracked as? Needs spading. In the data files we have
1 - CMC environment tracking "freezes" after your 5th consult, the pill available during the new rollover will be the same as the previous rollover, regardless of however many advcombats were done in between those things. CMC does not have to be active to track environments -- swapping workshed from say, Asdon, will offer a pill that respects the last 20 advcombats.

Cellar isn't a snarfblat and so doesn't have an environment. One of the bigger speed strats is to string together cellar with mist-shrouded icy peak as adv-taking non-environment places to burn down the CMC cooldown without affecting pill prediction.
 

Captain Scotch

New member
Hey all!

Just wanted to say major thanks on the CMC tracking. I am working on a script that will incorporate it into TourGuide, which should help me identify any tracking errors or issues. Really appreciate the discussion and the work on this, you all do great stuff, thanks for all the amazing KoLMafia development work you all do.

<3 Scotch
 
I had to read this quite a few times to understand it but are you saying that the environments stop being checked after the last consult? If so that's annoying because I've probably named this pref too widely.
yes, only I don't know that there is no other reason to record the last turn taking environment or that KoL won't change the CMC tracking after 5th use
 

Captain Scotch

New member
Hey folks!

KOL /dev cannonfire40 has alerted me to an issue with CMC tracking that should be a pretty easy fix.

The issue is located at line 4231 in FightRequest.java. Currently, the logic looks like this:
Code:
    var environment = location != null ? location.getEnvironment() : "none";

    var symbol =
        switch (environment) {
          case "outdoor" -> "o";
          case "indoor" -> "i";
          case "underground" -> "u";
          case "underwater" -> "x";
          default -> "?";
        };

However, this is slightly incorrect. For zoneless fights (Tavern rats, the Knott Yetis, the locket, etc), the real behavior is that the CMC does not append anything to the internal string KOL is storing. Cannon's suggestion was to fix this by encasing the setstring within a check that essentially ensures it doesn't get touched if mafia is aware the fight's environment is null.

Code:
if (location != null) {
      var environment = location.getEnvironment();
      
      var symbol =
          switch (environment) {
            case "outdoor" -> "o";
            case "indoor" -> "i";
            case "underground" -> "u";
            case "underwater" -> "x";
            default -> "?";
          };
      
      // Make sure the value is padded to handle malformed preferences
      var environments = "x".repeat(20) + Preferences.getString("lastCombatEnvironments") + symbol;
      
      Preferences.setString(
          "lastCombatEnvironments", environments.substring(environments.length() - 20));
    }
Let me know if you have any questions or want any spading to demonstrate this, we were bug checking for a bit so I have a few session logs and ample data to help back this one up :)

<3 Scotch
 

gausie

D̰͕̝͚̤̥̙̐̇̑͗̒e͍͔͎͈͔ͥ̉̔̅́̈l̠̪̜͓̲ͧ̍̈́͛v̻̾ͤe͗̃ͥ̐̊ͬp̔͒ͪ
Staff member
Thanks! That code snippet will not do what you think, but I will fix the issue regardless.
 
Top