Bug - Fixed crystalBallPredictions incorrectly reset

ckb

Minion
Staff member
This is related to (the same as) this bug: crystalBallMonster incorrectly reset

In some cases, "crystalBallPredictions" will be incorrectly reset to nothing (the property will be cleared) when the prediction is still true.
I believe this happens when the prediction gets set during a free turn (such as a free banish) and the next single turn is in the same location.
This is with r26269

In the example below this happens (all in The Haunted Library):

[22] fight banshee librarian, prediction=writing desk
[23] fight writing desk, prediction=banshee librarian
unequip the crystal ball
[24] encounter a banshee librarian anyway, use a no-turn banish (BOWL A CURVEBALL)
crystalBallPredictions is reset (now it is blank)
equip the crystal ball
[24] encounter a banshee librarian

The only way this last encounter should be possible is if the banshee librarian is still the crystalBallPredictions (because banshee should be banished)


Code:
[22] The Haunted Library
Encounter: banshee librarian
Round 0: ckb1 wins initiative!
Round 1: You take a look at ck-Boris's crystal ball, and see a tiny you fighting a tiny writing desk in a tiny... here.
Round 1: You lose 1 hit point
Round 1: ck-Boris dissolves some of your opponent's more important bits, leaving her weaker.
Round 1: banshee librarian drops 9 attack power.
Round 1: banshee librarian drops 9 defense.
Round 1: ckb1 executes a macro!
Round 1: ckb1 casts FEEL ENVY!
Round 2: ckb1 attacks!
Round 3: banshee librarian takes 256 damage.
Round 3: ckb1 wins the fight!
After Battle: Your Iunion stones twirl in intricate patterns as they absorb knowledge from the surrounding books.
The crown gains +1 Stat Gain per Fight
After Battle: You look into the crystal ball, and see someone who looks just like you, picking up sweet loot. Jealous! (+50 Item Drops)
After Battle: Traptrup whirls around picking up items, like a little couscous tornado.
After Battle: ck-Boris oozes around, picking up bits of debris from the battle.
You acquire an item: disintegrating quill pen
You acquire an item: killing jar
After Battle: You gain 19 Muscleboundness
You gain a Muscle point!
After Battle: You gain 39 Wizardliness
After Battle: You gain 14 Cheek
You gain a Moxie point!
After Battle: You spot an opponent hiding filed under 'Q' in the card catalog and prepare yourself to get the jump.
You acquire an effect: Cartographically Aware (5)

> CrystalBalltrn = 21, CrystalBallloc = The Haunted Library, CrystalBallmon = writing desk
> SetFam item-banish: +familiar, 5.0 familiar weight, 2.0 item drop, 0.1 meat drop = miniature crystal ball

[23] The Haunted Library
Encounter: writing desk
Round 0: ckb1 wins initiative!
Round 1: You look over ck-Boris's shoulder (or shoulder-analogue), and see yourself running into a banshee librarian soon.
Round 1: ck-Boris dissolves some of your opponent's more important bits, leaving it weaker.
Round 1: writing desk drops 9 attack power.
Round 1: writing desk drops 9 defense.
You acquire an item: cosmic bowling ball
Round 1: ckb1 executes a macro!
Round 1: ckb1 attacks!
Round 2: writing desk takes 147 damage.
Round 2: ckb1 wins the fight!
After Battle: You see yourself gaining experience in the crystal ball. (+5 Stats)
After Battle: Traptrup pirouettes in the air, searching for scattered items. Maybe he was a pierougi in a past life.
After Battle: ck-Boris oozes around, picking up bits of debris from the battle.
You acquire an item: inkwell
You acquire an item: snifter of thoroughly aged brandy
After Battle: ck-Boris shudders and disgorges an item with a wet squelch.
You acquire an item: Pick-O-Matic lockpicks
After Battle: You gain 14 Fortitude
After Battle: You gain 44 Wizardliness
You gain a Mysticality point!
After Battle: You gain 19 Chutzpah

> CrystalBalltrn = 22, CrystalBallloc = The Haunted Library, CrystalBallmon = banshee librarian
> Bad crystalBallMonster prediction @ 23
> SetFam item-banish: +familiar, 5.0 familiar weight, 2.0 item drop, 0.1 meat drop, -equip miniature crystal ball = none

[24] The Haunted Library
Encounter: banshee librarian
Round 0: ckb1 wins initiative!
Round 1: You lose 1 hit point
Round 1: ckb1 executes a macro!
Round 1: ckb1 casts BOWL A CURVEBALL!
This combat did not cost a turn

> CrystalBalltrn = 0, CrystalBallloc = none, CrystalBallmon = none
> SetFam item-banish: +familiar, 5.0 familiar weight, 2.0 item drop, 0.1 meat drop = miniature crystal ball

[24] The Haunted Library
Encounter: banshee librarian
Round 0: ckb1 wins initiative!
Round 1: You look in the mini crystal ball -- it looks like there's a writing desk prowling around nearby.
Round 1: You lose 1 hit point
Round 1: ckb1 executes a macro!
Round 1: ckb1 attacks!
Round 2: banshee librarian takes 196 damage.
Round 2: ckb1 wins the fight!
After Battle: The crystal ball predicts a future filled with excellent looting opportunities. (+50 Item Drops)
After Battle: ck-Bountiful gives you a extremely thorough back and scalp massage. Ahhhhhhhh.
After Battle: You gain 17 hit points
After Battle: You gain 14 Mana Points
After Battle: Traptrup spins and whirls in the breeze, like a spicy little dust devil.
After Battle: ck-Bountiful busts out the most elaborate breakdancing moves you've ever seen.
After Battle: You gain 20 Strengthliness
After Battle: You gain 42 Magicalness
You gain a Mysticality point!
After Battle: You gain 11 Chutzpah

> CrystalBalltrn = 23, CrystalBallloc = The Haunted Library, CrystalBallmon = writing desk
> SetFam item-banish: +familiar, 5.0 familiar weight, 2.0 item drop, 0.1 meat drop = miniature crystal ball
 
Confirmed this bug:
If you encounter a predicted monster with the crystal ball NOT equipped, Mafia will reset the prediction.
Equipping the crystal ball will then force the actual predicted monster, even though crystalBallPredictions is blank.
 
Looking through CrystallBallManager.java, it looks like isCrystalBallMonster() handles this by assuming that the correct monster in the correct zone is from the crystal ball.
It should also check that the crystal ball is equipped.

I know nothing about java, but maybe this would work:
(hacked from the other code in CrystallBallManager)

Code:
  public static boolean isCrystalBallMonster(final String monster, final String zone) {
    // There's no message to check for so assume the correct monster in the correct zone is from the
    // crystal ball
    AdventureResult ORB = ItemPool.get(ItemPool.MINIATURE_CRYSTAL_BALL, 1);
    for (final Prediction prediction : CrystalBallManager.predictions.values()) {
      if (prediction.monster.equalsIgnoreCase(monster)
          && prediction.location.equalsIgnoreCase(zone)
          && KoLCharacter.hasEquipped(ORB, EquipmentManager.FAMILIAR) ) {
        return true;
      }
    }

    return false;
  }
 
Confirmed this bug:
If you encounter a predicted monster with the crystal ball NOT equipped, Mafia will reset the prediction.
Equipping the crystal ball will then force the actual predicted monster, even though crystalBallPredictions is blank.
Honestly, I didn't know that was how it worked!
Looking through CrystallBallManager.java, it looks like isCrystalBallMonster() handles this by assuming that the correct monster in the correct zone is from the crystal ball.
It should also check that the crystal ball is equipped.

I know nothing about java, but maybe this would work:
(hacked from the other code in CrystallBallManager)

Code:
  public static boolean isCrystalBallMonster(final String monster, final String zone) {
    // There's no message to check for so assume the correct monster in the correct zone is from the
    // crystal ball
    AdventureResult ORB = ItemPool.get(ItemPool.MINIATURE_CRYSTAL_BALL, 1);
    for (final Prediction prediction : CrystalBallManager.predictions.values()) {
      if (prediction.monster.equalsIgnoreCase(monster)
          && prediction.location.equalsIgnoreCase(zone)
          && KoLCharacter.hasEquipped(ORB, EquipmentManager.FAMILIAR) ) {
        return true;
      }
    }

    return false;
  }
This is good, except I would run that check once before the for loop! Want to submit that as a PR?
 
PR submitted.
I am semi-sure its correct, but I have no way to verify as I don't know how to compile or check the java.
 
PR submitted.
I am semi-sure its correct, but I have no way to verify as I don't know how to compile or check the java.
I verified it by writing some tests! All merged now. Thanks
 
Back
Top