Bug Maximizer NullPointerException

ckb

Minion
Staff member
I seem to [sometimes] get a NullPointerException during Maximize in one of my scripts. Re-running the script after this happens continues as normal. Not sure what/why.
DEBUG log attached.
 

Attachments

  • DEBUG_20201007.txt
    28.4 KB · Views: 10

fronobulax

Developer
Staff member
What was ckb1 trying to do near turn 819 and 1188? Any chance the maximizer string got logged?

If you set scriptMRULength to something greater than zero the next debug log will include the last script that was "registered" as recently used, which might help.

I'd be interested in the items that are available for offhand use to ckb1 since that seems to be a consistent theme in the debug log.
 

MCroft

Developer
Staff member
I've started playing with the Maximizer dump/2 dump parameters recently. I wonder if that would fire before the error and list items being considered that might be null.
 

ckb

Minion
Staff member
I ran a few scripts... not sure which one caused this. I will keep track of the maximizer string for next time it happens. I pulled this string out of my logs - it is a typical maximize string from my script.

Code:
1 hand, -equip red shirt, -equip saucepan, -equip Helps-You-Sleep, -equip HOA zombie eyes, 0.05 MP regen, -50.0 combat rate, 0.1 familiar weight, 2.0 item drop, -0.001 mana cost, 0.8 meat drop, 1.0 spell damage, +equip The Crown of Ed the Undying, +equip latte lovers member's mug, -familiar
 

Veracity

Developer
Staff member
It's finding a null in your inventory. Can't even begin to speculate on how that happened.
 

ckb

Minion
Staff member
More info pulled from my sleepy head this morning... I have the property 'maximizerCombinationLimit=333333' currently.
With a very large inventory (in AfterCore) this sometimes fails to correctly meet all maximize requirements. Increasing the maximizerCombinationLimit sometimes helps, some I have noticed that if it is low enough, maximize runs a lot faster, but it will fail sometimes for a condition that is already met.
For example, including "outfit Frat Warrior Fatigues" in the maximize string with a low maximizerCombinationLimit, maximize will try to change equipment with a limited set and not meet all conditions - such as ending up without the Frat Warrior Fatigues outfit on. Running maximize again with the same string will yield the expected results of wearing the outfit.

Here is another post example I had, which I believe is related to this same issue of Maximize cutting short when maximizerCombinationLimit is low:
https://kolmafia.us/showthread.php?25144-maximizer-inconsistency


So... perhaps something with how Maximize is hitting this limit is causing it to give a result of 'null' for a piece of equipment and hence causing the NullPointerException.

My other hypothesis is that Maximizer with maximizerCombinationLimit will give different / inconsistent results depending on if some of the ideal equipment is currently being worn or not.
 
Last edited:

fronobulax

Developer
Staff member
I note the compareTo that is referenced in one of the logs is

Code:
		if ( this.compareTo( Maximizer.best ) > 0 )
		{
			Maximizer.best = (MaximizerSpeculation) this.clone();
		}

from MaximizerSpeculation.

best is a static member of MaximizerSpeculation and successfully executing this compare is only one of two places that I can find that it gets set. (The other is in Maximizer, I think but I closed the search and don't need the right answer badly enough to do it again).

I can certainly speculate about a code path where we are speculating and have not found anything good enough before we end up here.

There are two obvious actions - one would be to check best for null and not make the compare if it is. That leaves it unset but may just cause something further on to fail. The other would be to set best to the clone of this if best is unset or if this is better.

i.e.

Code:
		if ((Maximizer.best == null) || ( this.compareTo( Maximizer.best ) > 0 ))
		{
			Maximizer.best = (MaximizerSpeculation) this.clone();
		}

That approximates the pattern where you initialize a search with the first element.

This being the Maximizer and in the presence of a whole lot of recursion I'm reluctant to make that change solely on my own understanding but I would try it if there are no better suggestions.
 

fronobulax

Developer
Staff member
Well I am running with the Maximizer.best == null added and so far, no problems. Of course since I couldn't reproduce the dump my experience really means nothing.
 

ckb

Minion
Staff member
This happened again, and I looked into the script and the maximizer string when it occurred. I captured the output from the CLI and added it to the DEBUG log.

One thing I did note, is that my script does cli_execute("fold wad of used tape") before maximization. This happened when I was wearing wad of used tape. Is it possible that there was some confusion with that item and if it was equipped or in inventory?
The NullPointerException happens partway through the Maximize command.
 

Attachments

  • DEBUG_20201020.txt
    14.5 KB · Views: 3

ckb

Minion
Staff member
And another one. This time without any folding. :-(
 

Attachments

  • DEBUG_20201021.txt
    16.5 KB · Views: 3

MCroft

Developer
Staff member
What do you get when you enter this in the gCLI, with and without the fold? ( this version adds dump so we can see what it's considering, maybe...) Or you can put the dump version in your script just before the actual maximize to so you have a record of what you're considering...

Code:
maximize? 1 hand, -equip red shirt, -equip saucepan, -equip Helps-You-Sleep, -equip HOA zombie eyes, -equip Unkillable Skeleton's shield, -equip Time Bandit Badge of Courage, 0.05 MP regen, 0.1 familiar weight, 2.0 item drop, -0.001 mana cost, 0.8 meat drop, +equip Fourth of May Cosplay Saber, +equip Pantsgiving, +equip Mr. Screege's spectacles, +equip Mr. Cheeng's spectacles, -familiar , dump
 
Last edited:

ckb

Minion
Staff member
Just for giggles is ckb-One.ash, line 6383 "interesting"?

No, this is just the maximize command. mmx is the maximiser string:
Code:
maximize(mmx,false);

@MCroft, CLI from that maximization, no issues:

Code:
> maximize? 1 hand, -equip red shirt, -equip saucepan, -equip Helps-You-Sleep, -equip HOA zombie eyes, -equip Unkillable Skeleton's shield, -equip Time Bandit Badge of Courage, 0.05 MP regen, 0.1 familiar weight, 2.0 item drop, -0.001 mana cost, 0.8 meat drop, +equip Fourth of May Cosplay Saber, +equip Pantsgiving, +equip Mr. Screege's spectacles, +equip Mr. Cheeng's spectacles, -familiar , dump

Maximizer: 1 hand, -equip red shirt, -equip saucepan, -equip Helps-You-Sleep, -equip HOA zombie eyes, -equip Unkillable Skeleton's shield, -equip Time Bandit Badge of Courage, 0.05 MP regen, 0.1 familiar weight, 2.0 item drop, -0.001 mana cost, 0.8 meat drop, +equip Fourth of May Cosplay Saber, +equip Pantsgiving, +equip Mr. Screege's spectacles, +equip Mr. Cheeng's spectacles, -familiar , dump
Maximizing...
Outfits [Bounty-Hunting Rig]
SLOT 0
[training helmet, Crown of Thrones, Brimstone Beret, Goggles of Loathing, Hodgman's porkpie hat, Hairpiece On Fire]
SLOT 1
[]
SLOT 2
[(none)]
SLOT 3
[Bag o' Tricks, Ouija Board, Ouija Board, A Light that Never Goes Out, Half a Purse, Brimstone Bunker, Scepter of Loathing, Hodgman's imaginary hamster, Hodgman's metal detector]
SLOT 4
[balsam barrel, Buddy Bjorn]
SLOT 5
[flaming pink shirt, (none)]
SLOT 6
[Pantsgiving]
SLOT 7
[Mr. Cheeng's spectacles, Mr. Screege's spectacles, ring of the Skeleton Lord, Belt of Loathing, musty moccasins, Brimstone Bracelet, Brimstone Brooch, Pocket Square of Loathing, Treads of Loathing, Hodgman's bow tie, Hand in Glove, stuffed carpenter, Hodgman's lucky sock]
SLOT 8
[Fourth of May Cosplay Saber]
SLOT 9
[bottle-rocket crossbow, Sheila Take a Crossbow]
SLOT 10
[amulet coin]
SLOT 11
[(none)]
SLOT 12
[(none)]
SLOT 13
[glow-in-the-dark wristwatch]
SLOT 14
[Fourth of May Cosplay Saber, Spelunker's whip, Brimstone Bludgeon, Stick-Knife of Loathing, Staff of the Headmaster's Victuals, Sheila Take a Crossbow, Work is a Four Letter Sword]
SLOT 15
[]
SLOT 16
[]
SLOT 17
[]
SLOT 18
[]
SLOT 19
[(none)]
SLOT 20
[(none)]
SLOT 21
[(none)]
SLOT 22
[]
SLOT 23
[]
30948 combinations checked, best score 1,283.68
70347 combinations checked, best score 1,283.68
109799 combinations checked, best score 1,283.68
150217 combinations checked, best score 1,283.68
190557 combinations checked, best score 1,283.68
229927 combinations checked, best score 1,283.68
269073 combinations checked, best score 1,283.68
308292 combinations checked, best score 1,283.68
333333 combinations checked, best score 1,283.68
 

MCroft

Developer
Staff member
No, this is just the maximize command. mmx is the maximiser string:
Code:
maximize(mmx,false);

@MCroft, CLI from that maximization, no issues[...]

Well, given that you said it was possible to run the same thing in the maximizer (or the gCLI), that's not really a surprise. It's somehow intermittent, if I recall what you said earlier.

What you could do do is add the dump parameter to the maximize string mmx, so that when it dies you can get the error.

Also, since you have r > 20456, you could implement some of Veracity's try/catch logic.
 

MCroft

Developer
Staff member
I am not sure how to implement this (I am not a programmer and am new the concept of 'catch'). Can you give an example of how I would use this with maximize?

Here's an intro to the concept.

ASH is a little different, but it's not that different.
catch ( string message ) {} - catch anything. The message goes in the (scoped) variable
You do the risky thing inside the braces, and if there's an error, instead of dying a pitiful death on a forsaken beach 15.3 parsecs from home, the code pops the error into the string variable message. You can then print it, use it in "if" statements, decide to dump a bunch of useful data to the console or (if you're brave) just retry something...

I'd expect this to look like
Code:
catch (String errorCondition) 
{
  maximize(mme, false);
}
if ! ( errorCondtion.equals( "" ) ) 
{
  //dump a bunch of error related stuff, including errorCondition and mmx to the console so that it's easier to chase down the error
}

as a bonus, you can report to Veracity on how this worked for you.
 

Veracity

Developer
Staff member
Given what I've done so far, it'd be:

Code:
string errorCondition = catch
{
  maximize(mme, false);
}
if (errorCondition != "" ) ) 
{
  //dump a bunch of error related stuff, including errorCondition and mmx to the console so that it's easier to chase down the error
}
Except I don't think I have catch-returning-a-value coded yet for more than catching a simple statement.
I also have not tried catching actual Java errors; only "continuation errors" when ASH library functions return a value which will stop your script if not captured.

Eventually it will be:

Code:
try
{
  maximize(mme, false);
}
catch ( string errorCondition )
{
  //dump a bunch of error related stuff, including errorCondition and mmx to the console so that it's easier to chase down the error
}
But that is aspirational; I have not worked on that yet. This project is nowhere near done.

I'll work more on this this afternoon.
 
Last edited:
Top