Bug - Fixed appearance_rates(loc, true) gets confused

zarqon

Well-known member
The appearance_rates() function could be made much more reliable if it were to correctly account for monsters with 0% appearance rates in the zone.

My combat queue for the Haunted Bathroom is as follows: toilet papergeist; claw-foot bathtub; toilet papergeist; malevolent hair clog; cosmetics wraith

This results in appearance rates of infinity!

> ash appearance_rates($location[the haunted bathroom],true)

Returned: aggregate float [monster]
claw-foot bathtub => ∞
Guy Made of Bees => 0.0
malevolent hair clog => ∞
none => 25.0
toilet papergeist => ∞

I seem to recall that wandering monsters (of which there are increasingly more) likely produce the same effect.

My combat queue for The Laugh Floor is: Carbuncle Top; Victor the Insult Comic Hellhound; Pr Imp; CH Imp; BL Imp

> ash appearance_rates($location[the laugh floor],true)

Returned: aggregate float [monster]
BL Imp => -33.333333333333336
Carbuncle Top => 0.0
CH Imp => -33.333333333333336
Larry of the Field of Signs => 0.0
none => 0.0
Pr Imp => -33.333333333333336
Victor the Insult Comic Hellhound => 0.0

All of the monsters are listed as having a sum -100% chance of occurring.

My combat queue for the Throne Room is simply: Aquagoblin

> ash appearance_rates($location[throne room],true)

Returned: aggregate float [monster]
Knob Goblin King => 400.0
none => 0.0

The appearance rate of the King should probably be listed as 0% until such time as mafia starts trying to account for special cases. But that aside, it does show that appearance rates well over 100% are occurring, which should be impossible.

EDIT: EXTRA CREDIT! It would be super cool if, while fixing this, appearance_rates(true) were also made to treat banished monsters as having an appearance rate of 0.
 
Last edited:

Bale

Minion
It is fascinating to see the odd corners of KoLmafia that your unique muse guides you into.
 

Darzil

Developer
Yeah, that whole piece is a mess. When I wrote the banishing code I spent several hours looking at how to add it to this, and trying things, that then failed to work.

I also think that it'd be good if it handled the new types of scheduled or conditional non-combats (so like hidden city for the first, and spooky forest/giant's castle for the latter) as well as straight combat rates. Then of course we'd also need to show either overall rate (which it is now) or chance on next adventure (which is what combat chance is). And maybe non-combats that can be banished too!

At that point though you are virtually starting that section of code again!
 

lostcalpolydude

Developer
Staff member
It looks like things need to be removed from zoneSet that can't actually appear in the zone (encounter rate of 0, or just not present in that zone) before using its size to adjust the denominator.
 

lostcalpolydude

Developer
Staff member
I have code all written to fix this. (At least, I initially saw the same issues as the original post, and now I see proper results from those same commands.) However, I feel like the correct way to handle this is probably to not add those monsters to the queue in the first place. Wandering monsters are clearly not part of the monster selection list for a zone, and anything with a weight of 0 is likely determined in some way other than selecting a monster from the zone's list.

This would be a bit of a change in functionality, including weird effects like messing up the MCD warning for the boss bat (since it looks at how many monsters are in the combat queue). Path-specific monsters wouldn't show up in the queue even though they should, but they currently won't affect appearance_rates() anyway, and that would be a lot of extra work to add proper support there (I'm thinking Bugbear Invasion in particular).

So, I'm looking for feedback on which fix would be better: keeping the queue the way it currently is and just ignoring monsters that "shouldn't" be there for calculations, or not adding those monsters to the queue to begin with.
 

Darzil

Developer
Well, we'd certainly want to be able to work out how many turns have been spent in a location, as it's used in loads of places in guide, for example. There are so many places delay is important.

I'd suggest keeping the queue the way it is, and ignoring monsters that aren't from that location for calculations (unless relevant for queue effects, I'm pretty ignorant on how that works).
 

lostcalpolydude

Developer
Staff member
Fixed in 14674. Mafia doesn't really have support for turns spent in a location, since there are so many places where you care about more than 5 turns (outskirts of cobb's knob, castle ground floor, airship), but supporting that would also require recognizing encounters that shouldn't increase the count (any noncombat that doesn't use a turn, I guess).

As for the extra credit portion of the initial post, supporting banishing would also require supporting olfaction and nosy nose.
 

zarqon

Well-known member
Thanks very much lost! BatMan RE's Adventure Again box will now have much more reliable information about what monster you can expect next thanks to this fix.
 

Darzil

Developer
As for the extra credit portion of the initial post, supporting banishing would also require supporting olfaction and nosy nose.
Ok, have been looking at the adventure queue wiki page. Without looking at our code, I think what we'd need would be:
We'd have to build our base encounter rate list (weight) and add extra copies for olfaction, nosy nose, staff of the cream and make friends (most we should have is 4 extra copies per original if nose and olfaction stack). Rejection chance reduces the adjusted weight by a %, so we can have non integer values (and we'd have to find out and capture rejection %'s). If banished and not olfacted, don't include the monster at all. We'd probably have to explicitly handled some edge cases (hidden city monster moves, Dis boss unlocks).

If no olfaction, we can use the adventure queue equation given on the wiki.

If olfaction, I think we probably will have to generate a lookup table of simulation of all the possible values, which by the above looks like a LOT. Or maybe we can be less accurate and run a simulation through a certain number of iterations live? It's a relatively small iteration compared to things like modifier maximizer.

If simulation is the way to go, maybe we can just run with it for all. Maybe with a preference to switch it off for performance or on for accuracy. Could even allow the preference to specify the number of iterations to try, so users can tune their preferences.

Probably a rather large dataset for olfaction is better.
 

lostcalpolydude

Developer
Staff member
If it's going to be that accurate, there are cases like the Astronomer that aren't handled properly either. Instead of 3 for it and 2 for everything else it should be 2 and 1, but with a 25% rejection chance on the Astronomer in any given turn. There are other cases like that too. That rabbit hole can go pretty deep.
 

Darzil

Developer
Yeah, we could do a stage 1 of more accurate where we only handle the additional copies bit of olfaction, but everything else. That wouldn't be too bad. For things like Astronomer does the maths make it actually a 1.5 encounter rate (and 0.2 for wild seahorse) or does the rejection actually change the numbers?
 

Darzil

Developer
Some thinking, it looks like rejection does change the numbers, and partial encounter rates wouldn't work for sim anyway.

Use equation if :
No relevant olfaction and no rejection condition on zone monster
Otherwise sim (number of times in a preference to allow speed/accuracy tuning, 0 = don't sim, always use equation and accept it is inaccurate)
Maybe don't sim at all during automatic adventuring for performance?

Need to handle:
Build arrays of information first, don't want to have to hit other functions whilst in sim for speed.
Rejection (add Reject: X in monsters.txt, consider in sim)
Test if adventure area has conditionals/rejection (add function to AdventureDatabase)
Conditionals (I think this needs to be added as a function, lots of individual cases, some tracking will need adding for some, if sim, will consider during sim, to handle Tavern Cellar, Modern Zombies etc)
Banishes (don't include unless all banished and no conditional in area)
Olfaction (in sim, +3 copies and change to handling, non sim, +3 copies)
Staff of the Cream of the Cream (+2 copies)
Nosy Nose (+1 copy - does this stack with 3 from olfaction?)
Make Friends (+ 3 copies)
Return array of monsters/rates rather than rate for one monster so we only sim once.

Things we could consider:
Semi-rares, if counter known and due and there is one in area, 100% chance for that, 0% for all else. If several known and there is one, 1/number chance for that, multiply others by (1-1/number). If range known, 1/41 chance for non-oxy, 1/21 for oxy, multiply others by (1-1/range). If none known, 1/180 for non-oxy, 1/110 for oxy.
Chance of wandering monster.
Guaranteed non-combats (will need tracking added).
Extreme accuracy would also want to include knowledge of whether missed semi-rare or wandering monster turns happened in adventure.php or not. We'd also be adding things like wandering monster counters not expiring til one is met (which might be worthwhile, actually), and wanting to know which takes priority.
 

heeheehee

Developer
Staff member
Modern zombies are just really weird because they're actually superlikely. Tavern cellar has its own combat selection process. It rolls for combat / noncombat, then checks to see if you get a rat king, then checks if you get a bunch of drunken rats, then just chucks a rat at you.

Technically other places like Oil Peak and Slime Tube are full of conditional monsters. This might actually be relevant, given that tumbleweeds can appear in those places.

KingBobson mentioned something in /clan the other day about priority of wandering monsters. I assume he's going to spade that soon enough.
 

Darzil

Developer
Definitely not going to add a simulation for queue effects under rejection or olfaction. We can't afford the overhead with the amazing amount the recalculate() function is hit.

Changing adventure location in Mafia caused AreaCombatData.recalculate() to be hit 8 times.
After each combat round it is hit twice.
Automation hits it 8 extra times in the first round.
After an automated fight it was hit 14 times.
After a relay browser fight (with CHIT) it was hit 26 times.
 

Darzil

Developer
Also our adventure queue equation is the basic one from the wiki, which assumes equal probabilities of all monsters (http://kol.coldfront.net/thekolwiki/index.php/Adventure_Queue) with that then just multiplied by the number of a type of monster in the zone. We should move to the more advanced one that allows for unequal probabilities.

I wonder if there are maths wizzes out there who could calculate the equations taking into account rejection chance (maybe that just alters base probability?) and olfaction (I guess that'll have different equations for olfaction of monster you want, in and out of queue, and olfaction of another monster in zone, in and out of queue) ?
 

Darzil

Developer
r14687 properly accounts for queue effects when base encounter weightings are not the same in a zone. It takes account of the encounter weighting (number of copies in the encounter pool) effects of Olfaction, Make Friends, Cream staff and Nosy Nose. If none of these are present, banish sets weight to -3 and it is assumed to be unencounterable. Track Make Friends monster and Nosy Nosy Whiff monster.

Assumptions that may be faulty:
Banish doesn't reduce number in the encounter pool if the monster is affected by a +copies effect. (ie if you use Nosy Nose then banish, there are 2 copies rather than 1 in the pool. If Olfaction, 4 rather than 3, etc)
Nosy Nose and Olfaction stack.
Nosy Nose only has an effect when the current familiar.

It does NOT take into account queue rejection behaviour of olfaction.
 

Darzil

Developer
Assumptions that may be faulty:
Banish doesn't reduce number in the encounter pool if the monster is affected by a +copies effect. (ie if you use Nosy Nose then banish, there are 2 copies rather than 1 in the pool. If Olfaction, 4 rather than 3, etc)
It was faulty, and r14688 fixes it.
 

heeheehee

Developer
Staff member
Based on http://ludonomicon.com/kol/qcalc.html and 1700ish trials (tattering in backstage, with one monster ice housed, so monster in question was always trailed),
Code:
55.991% +4 copies, ignore the queue
43.793% +3 copies, ignore the queue
0.216% +5 copies, ignore the queue
I... should have probably tried a zone with more monsters. Be back on another multi with some spading results :p
 
Last edited:
Top