New Content - Implemented Rethinking Candy

Bale

Minion
KingBobson has figured out how Rethinking Candy works. Unfortunately for us it reveals that there are two levels of candy. He calls them simple and complex, but we could call them level 1 and level 2 candies. Or whatever. Regardless, as candy level gets spaded we need to be able to add that information to KoLmafia's data files.


BTW, here's the deal for Rethinking Candy: http://forums.kingdomofloathing.com/vb/showpost.php?p=4890935&postcount=568
Paraphrased from KingBobson's post said:
The effects have different effect images; either molecule1.gif, molecule2.gif, or molecule3.gif. I'm going to assume they're tiered.

Tier 1, #0 - Synthesis: Hot. Sublime (+9) Hot resistance.
Tier 1, #1 - Synthesis: Cold. Sublime (+9) Cold resistance.
Tier 1, #2 - Synthesis: Pungent. Sublime (+9) Stench resistance.
Tier 1, #3 - Synthesis: Scary. Sublime (+9) Spooky resistance.
Tier 1, #4 - Synthesis: Greasy. Sublime (+9) Sleaze resistance.

Tier 2, #0 - Synthesis: Strong. +300% Muscle.
Tier 2, #1 - Synthesis: Smart. +300% Mysticality.
Tier 2, #2 - Synthesis: Cool. +300% Moxie.
Tier 2, #3 - Synthesis: Hardy. +300% Maximum HP.
Tier 2, #4 - Synthesis: Energy. +300% Maximum MP.

Tier 3, #0 - Synthesis: Greed. +300% Meat.
Tier 3, #1 - Synthesis: Collection. +150% Items.
Tier 3, #2 - Synthesis: Movement. +50% Muscle gains.
Tier 3, #3 - Synthesis: Learning. +50% Mysticality gains.
Tier 3, #4 - Synthesis: Style. +50% Moxie gains.

Every buff has a 'number', 0-4, and a tier. It's sorted by effect ID.
The maths for seeing what number of the correct buff tier you get is just (item1ID + item2ID) % 5.

Tier 1 is for mixing simple and simple candies,
Tier 2 for simple and complex (or complex and simple),
Tier 3 is for complex and complex.

As an example: bag of W&Ws has itemID 6835. (6835 + 6835) % 5 = 0, so that means you get buff #0. Since bag of W&Ws is a complex candy, you get Synthesis: Greed.
(Note: Because of how modulo and addition interact, you can perform it individually on every item before combining them, if that makes it easier. So you could call W&Ws #0, and then you'd know if you combined it with a #4 you'd get buff #(0+4 = 4). Of course, if that addition leads to #7 or something, then you have to subtract five to get the real answer, #2).

The only thing left to investigate is what makes a candy simple rather than complex. I have no idea, but there is certainly a rule behind it, because I am able to consistently predict ahead of time which one it'll be. All Halloween candies are complex, I believe, but there are non-Halloween candies that are too (for example, peanut-brittle shield). Any candy that you can get a 'normal, non-Halloween' way is simple, but that seems hard to nail down.
 
Last edited:

lostcalpolydude

Developer
Staff member
How would this info about candy type be provided? Does the candy field get changed from a boolean to something else (string?), even though that would likely break some script? Maybe "", "unknown", "type1", "type2", as one possibility. Having "unknown" would make it easier for people to find candy to identify if desired.
 

Bale

Minion
Or to avoid breaking scripts (are there any script that check if candy is true?) you could add a new field, candy_type. I'm okay with either implementation.
 

heeheehee

Developer
Staff member
Casting sweet synthesis takes you to Choice 1217, where you need to specify a=$ITEM1, b=$ITEM2, and option=1.

Copy-paste from session logs (including the corresponding numbers needed to create items, although there weren't any surprises there -- KingBobson had the effects listed in order of effect ID):
Code:
cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=6833&b=6836&whichchoice=1217&option=1&pwd
--------------------
2179	Synthesis: Style	molecule3.gif	3eac42a54fbbf3270e7f8d045ae0f98d
Effect	Synthesis: Style	Experience Percent (Moxie): +50
--------------------
You acquire an effect: Synthesis: Style (30)
Took choice 1217/1: unknown
choice.php?a=6833&b=6833&whichchoice=1217&option=1&pwd

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=6836&b=6835&whichchoice=1217&option=1&pwd
--------------------
2176	Synthesis: Collection	molecule3.gif	c4b32a8af96620346e2898c4d875ce24
Effect	Synthesis: Collection	Item Drop: +150
--------------------
You acquire an effect: Synthesis: Collection (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=6835&b=6835&whichchoice=1217&option=1&pwd
--------------------
2175	Synthesis: Greed	molecule3.gif	bcba6799f907f44d5a10d4cd8aaf8b64
Effect	Synthesis: Greed	Meat Drop: +300
--------------------
You acquire an effect: Synthesis: Greed (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=6834&b=540&whichchoice=1217&option=1&pwd
--------------------
2174	Synthesis: Energy	molecule2.gif	856f0ec800a8b125ad0b1104f1a66fbb
Effect	Synthesis: Energy	Maximum MP Percent: +300
--------------------
You acquire an effect: Synthesis: Energy (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=2306&b=2306&whichchoice=1217&option=1&pwd
--------------------
2167	Synthesis: Pungent	molecule1.gif	2f04d1a794547d3f0f809fe0995d46b2
Effect	Synthesis: Pungent	Stench Resistance: +9
--------------------
You acquire an effect: Synthesis: Pungent (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=540&b=2306&whichchoice=1217&option=1&pwd
--------------------
2166	Synthesis: Cold	molecule1.gif	daa3e18133e0139ab932034b043f8a94
Effect	Synthesis: Cold	Cold Resistance: +9
--------------------
You acquire an effect: Synthesis: Cold (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=2307&b=6835&whichchoice=1217&option=1&pwd
--------------------
2172	Synthesis: Cool	molecule2.gif	f88b5aa9cf481f4ce178a58b61e1278c
Effect	Synthesis: Cool	Moxie Percent: +300
--------------------
You acquire an effect: Synthesis: Cool (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=298&b=6835&whichchoice=1217&option=1&pwd
--------------------
2173	Synthesis: Hardy	molecule2.gif	43d63c6c27ef2b297417987e89d3749e
Effect	Synthesis: Hardy	Maximum HP Percent: +300
--------------------
You acquire an effect: Synthesis: Hardy (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=6835&b=6833&whichchoice=1217&option=1&pwd
--------------------
2178	Synthesis: Learning	molecule3.gif	2ab58c6dc401f84bde540ee4381aa923
Effect	Synthesis: Learning	Experience Percent (Mysticality): +50
--------------------
You acquire an effect: Synthesis: Learning (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=6836&b=6836&whichchoice=1217&option=1&pwd
--------------------
2177	Synthesis: Movement	molecule3.gif	8fc6d4d7a4a762291af19f4dce1f9968
Effect	Synthesis: Movement	Experience Percent (Muscle): +50
--------------------
You acquire an effect: Synthesis: Movement (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=2307&b=298&whichchoice=1217&option=1&pwd
--------------------
2165	Synthesis: Hot	molecule1.gif	70c1f50c4b1f77c7a6b2770d368a8392
Effect	Synthesis: Hot	Hot Resistance: +9
--------------------
You acquire an effect: Synthesis: Hot (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=2306&b=2307&whichchoice=1217&option=1&pwd
--------------------
2168	Synthesis: Scary	molecule1.gif	d6716e91a89a172640caf154f3204b52
Effect	Synthesis: Scary	Spooky Resistance: +9
--------------------
You acquire an effect: Synthesis: Scary (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=2307&b=2307&whichchoice=1217&option=1&pwd
--------------------
2169	Synthesis: Greasy	molecule1.gif	16edc9d5664e731bdd7a301b868f51fa
Effect	Synthesis: Greasy	Sleaze Resistance: +9
--------------------
You acquire an effect: Synthesis: Greasy (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=2306&b=6834&whichchoice=1217&option=1&pwd
--------------------
2170	Synthesis: Strong	molecule2.gif	bf0690a153910730d4dac25af85afd26
Effect	Synthesis: Strong	Muscle Percent: +300
--------------------
You acquire an effect: Synthesis: Strong (30)

cast 1 Sweet Synthesis
Encounter: Sweet Sythesis
Took choice 1217/1: unknown
choice.php?a=2307&b=6834&whichchoice=1217&option=1&pwd
--------------------
2171	Synthesis: Smart	molecule2.gif	a01998ee94700aeb5b4e88709829e416
Effect	Synthesis: Smart	Mysticality Percent: +300
--------------------

Candy hearts are "simple" (for now, at least), which should be convenient for getting specific buffs in aftercore. Not so sure of in-run utility, except maybe around Halloween, or maybe in unrestricted paths.
 

Ezandora

Member
These do not seem to be candy, but are marked as candy in mafia:
Code:
ironic mint
vial of blood simple syrup
little red jam
Bugbearclaw Donut
fudge-shaped hole in space-time

These seem to be candy, but mafia does not know about them:
Code:
candycaine powder
giant green gummi bear
giant green gummi ingot
giant red gummi bear
giant red gummi ingot
giant yellow gummi bear
 

Veracity

Developer
Staff member
Ezandora wrote a nice tool do help understand this skill. I was going to use this to enter the candy levels in items.txt, but lost beat me to it. Thank you!

Here are my thoughts on how to handle this in (up to) five phases. I'll describe each in detail.

We will end up with four new files:

persistence/CandyDatabase.java - data structures and utilities to manipulate candy
request/SynthesisRequest.java - handles casting the skill, logging GUI or Relay Browsers casting, inventory manipulation
textui/commands/SynthesisCommand.java - the "synthesis" CLI command
swingui/panel/SynthesizePanel.java - a panel for the Item Manager (ala Pulverive) to let you choose candy to combine to get a desired effect.

Obviously, there will be changes to lots of other files along the way:

KoLmafiaCLI
RequestLogger
persistence/ItemDatabase
session/ResponseTextParser
textui/RuntimeLibrary
textui/parsetree/ProxyRecordValue

and so on

******Phase 1******

Candy data.

- tag "candy" items in items.txt as:

candy - unspaded
candy1 - "simple" candy
candy2 - "complex candy

lost did this. Thank you!

- when ItemDatabase parses items.txt, for any of the above, it calls CandyDatabase to register it.
CandyDatabase has three Sets of itemIds:

tier0Candy
tier1Candy
tier2Candy

- ASH $item proxy:

boolean ITEM.candy -> true if any candy
int ITEM.candy_tier -> 0, 1, 2

Effect data.

- ASH $effect proxy:

int EFFECT.candy_tier -> 0, 1, 2, 3

0 = non-synthesis
1 = tier 1, tier 1
2 = tier 1, tier 2
3 = tier 2, tier 2

- "checkcandy" command

Simply lists all the unspaded candies

- "checkitems" command

When we see that the description says an item is a candy, allow "candy", "candy1" or "candy2".
ItemDatabase generates the "item line" for candy with candy, candy1, candy2, as appropriate

- "test newitem" (and hence ItemDatabase.registerItem)

For candy items, enter into CandyDatabase

The above has all the "data" we will need and exposes it to ASH, which would allow (tedious) programs to be written to deal with candy synthesis.

******Phase 2******

Using the skill.

- SynthesizeRequest does what is necessary to cast the skill and handle inventory.

- CLI commands in SynthesizeCommand:

synthesize CANDY1, CANDY2

"acquires" CANDY1 and CANDY2 and uses the skill, if acquisition succeeds

synthesize? CANDY1, CANDY2

tells you which effect this combination of candy will produce

We will do fuzzy matching on "candy" items for both CANDY1 and CANDY2

for each of CANDY1, CANDY2:
-- how many are "easily accessible" (no mall or clan)
-- mall price
-- simulated result of "acquire": fail, use, pull from storage, take from closet, buy, whatever
result of attempting skill:
FAIL - you cannot acquire (at least) one candy
SUCCEED - and total "value" of the two ingredients, even if you use one or both from what you already own.

- ASH functions in RuntimeLibrary:

boolean candy_synthesis( item candy1, item candy2 )

Does retrieve_item() on candy1 and candy2, casts the skill, and returns true - or false, if failed to retrieve. The equivalent of the "synthesize" command.

effect candy_synthesis_prediction( item candy1, item candy2 )

The "simulated" result of doing the above - either the resulting effect, if it would succeed, or $effect[ none ] if retrieval would fail

This phase will allow people to use Ezandora's tool to explore options and then make it so via KoLmafia.

******Phase 3******

ASH support in RuntimeLibrary using internal functions in CandyDatabase:

item [int] candy_tier( int tier )

Returns an array of all candy in tier 1 or 2 (or 0, if you want to spade). This will be ordered randomly.

You could do the following:

item [int] candy = candy_tier( 1 );
sort candy by -available_amount( value );
sort candy by -mall_price( value );

... to sort by high-to-low "easily available count" or "mall price", as appropriate

item [int] candy_synthesis_pairing( effect eff, item candy1 )

Returns an array of all candy that will synthesize with candy1 to produce eff. Note that the array can be empty if you ask for a tier 1 effect and give it a tier 2 candy or ask for a tier 3 effect and give it a tier 1 candy.

This is probably all the ASH support needed to write a smart script which will get you the desired effect "cheaply".

******Phase 4******

A panel in the Item Manager to let you do this.

At the top:

3 rows of 5 buttons each: the Tier 1, Tier 2, and Tier 3 effects:

Beneath:

Two (blank) text panes: Candy A and Candy B

At the Right:

(Disabled) "Synthesize!" button

Candy A
Have:
Cost:

Candy B:
Have:
Cost:

When you press one of the 15 Effect buttons, it highlights.
The Candy A pane fills with a table of candies, populated from Tier 1 or Tier 2, depending on the Effect tier
Each row has three columns:
Name
Count
Cost

As is usual for such tables in KoLmafia, click on the column head to sort on that column

If you press another Effect button, the previous one unhighlights (and the table clears) and the new one highlights and replaces the Candy A table.

If you select a candy in the Candy A table, the Candy B table fills with a table of all candies that will synthesize with the selected candy to produce the desired effect. As expected, you can sort on the three columns there, too. Additionally, the Have and Cost fields in the right for Candy A will have numbers.

If you select a different candy in Candy A, the Candy B table and the Candy A data in the right change appropriately.

If you select a candy in Candy B, the Candy B data on the right are filled in and the Synthesize! button is enabled.
If you deselect the candy, the values are cleared and the button is disabled.

If you click on the Synthesize! button, it acquires Candy A and Candy B and synthesizes the desired effect.

******Phase 5******

Allow automatic generation of the effect, as requested:

CLI command:

synthesize EFFECT
synthesize? EFFECT

Use some algorithm to calculate the "cheapest" two candies to use to get the desired effect. And yes, some people will want to consider "candy in inventory" to be worth 0 and some will want to consider it to be worth the mall price. Same old controversy.

- "up EFFECT" can use that command
- You can put it in a mood
- You can use it with the maximizer

I consider this phase to be optional. Personally, I want control over which candies will be used and when, so the GUI will suffice for me.

******

Thoughts?
 

lostcalpolydude

Developer
Staff member
I hadn't really thought past phase 1.

boolean ITEM.candy -> true if any candy
int ITEM.candy_tier -> 0, 1, 2
The candy boolean seems redundant, unless it's being kept for backwards compatibility. candy_tier could be 0, 1, 2, 3, with 1 being unknown, so a script can check for candy_tier > 0.
 

Veracity

Developer
Staff member
Well, I was thinking the "candy" proxy field would be for backward compatibility. But yes - candy_tier 0 could be "not a candy", candy_tier 1 could be "candy", candy_tier 2 could be "candy1" and candy_tier 3 could be "candy2", per the keywords in items.txt. That would be adequate which want to deal with candies qua candy, rather than as "candidates for synthesis".

However, further thought makes me think that the user/programmer who is interested in synthesis will not care about "candy1" vs. "candy2" candies. They will only care about the "candy tier" of an effect - which will be 1, 2, or 3.

Code:
item [int] candy_tier( int tier )

Returns an array of all candy in tier 1 or 2 (or 0, if you want to spade). This will be ordered randomly.
No. I think tier should be 1, 2, or 3 - which are "candy effect tiers".

(0 - every unspaded "candy")
1 - every "candy1"
2 - every "candy1" and "candy2"
3 - every "candy2"

An ASH program would do the following (as we can see from user actions in the GUI):

1) Choose an effect and see which "tier" it is in - 1, 2, or 3
2) Get the list of candidates from that tier
3) Choose candy A
4) Get the list of candidates given effect and candy A
5) Choose candy B

Operationally:

- tier 1 effect: first list is candy1 and second list is (subset of) candy1
- tier 2 effect: first list is candy1 and candy2 and second list is (subset of) candy2 or candy1, depending on which candy you first choose
- tier 3 effect: first list is candy2 and second list is (subset of) candy2

If the program REALLY wants every "candy1" (per items.txt), it would ask for "tier 1" and every "candy2" (per items.txt) would be "tier 3".

In which case "tier 0" could be all "candy" (per items.txt) (unspaded) candies.

Also, I showed you how to sort by mall_price from high to low. Obviously, you'd prefer to sort from low to high. :)

I think that should be the default order that we show candies in the GUI, too.
 

Bale

Minion
The candy boolean seems redundant, unless it's being kept for backwards compatibility. candy_tier could be 0, 1, 2, 3, with 1 being unknown, so a script can check for candy_tier > 0.

Value for a "not candy" should be -1. (It's just more consistent.) Then a script could check for candy_tier >= 0. Though I imagine scripts will mostly use candy_tier() to find relevant candies.
 

Veracity

Developer
Staff member
Yeah, -1 for "not a candy" is good.

Also, CandyDatabase will have 4 item sets:

tier0Candy - every "candy"
tier1Candy - every "candy1"
tier2Candy - every "candy1" and "candy2"
tier3Candy - every "candy2"

As well as a "canonical name array" built from tier2Candy, which can be used for "fuzzy matching" of all candy items.
 

Veracity

Developer
Staff member
Actually, given that:

string ITEM.candy_tier -> "none", "unspaded", "simple", "complex"
int EFFECT.candy_tier -> 0, 1, 2, 3 -> "not usable for synthesis", "tier 1 synthesis", "tier 2 synthesis", "tier 3 synthesis"
 

Bale

Minion
string ITEM.candy_tier -> "none", "unspaded", "simple", "complex"

I'd prefer to keep the proxy record as an int. -1, 0, 1, 2. Because I find integers easier to work with, but I could adapt if you really prefer strings.
 

Veracity

Developer
Staff member
I don't feel strongly, but I'm wondering how your program would use the item's "candy tier" rather than the effect's "candy tier".

If you use candy_tier() to get an array of candidates, you are passing in an effect's "candy_tier".
If you use candy_synthesis_pairing() to get an array of candidates, you are passing in an effect (in effect, an effect "candy_tier") and a candy.

I guess if you are writing a script to manipulate raw items before the phase 3 ASH functions come in, you might prefer a number in the item's candy_tier. But, once phase 3 is done, why will you need to look at that proxy field in the item?
 

Bale

Minion
I agree that any script is more likely to use the functions rather than checking raw item data. I'll probably never use the proxy record, but if I was to use the proxy record, the integer would be easier.
 

Veracity

Developer
Staff member
Good point.

If a skill has a "candy tier" and items do not and the candy_tier( int tier ) method exists to return a set of items that can be used to get you that "tier" of effect, seems like scripts are being directed to use the tools that are available to make their life easy.
 

Veracity

Developer
Staff member
OK, here is the updated phase 1-5 development plan. I'll probably start on it tomorrow.
Phases 1-3 should be straightforward.
Phase 4 is GUI work - my non-forte - including things I haven't done before.
Phase 5 requires a little research, although Ezandora's script is inspiring; simply choosing the cheapest total mall price for the two required candies will probably end up being really cheap, modulo major mall manipulation.

And the "synthesize" command and SynthesizeRequest have to remember that doing this uses a spleen...

******Phase 1******

Candy data.

- tag "candy" items in items.txt as:

candy - unspaded
candy1 - "simple" candy
candy2 - "complex candy

lost did this. Thank you!

- when ItemDatabase parses items.txt, for any of the above, it calls CandyDatabase to register it.

CandyDatabase has four Sets of itemIds:

Set<Integer> tier0Candy - all "unspaded" candies
Set<Integer> tier1Candy - all "simple" candies
Set<Integer> tier2Candy - all "simple" and "complex" candies
Set<Integer> tier3Candy - all "complex" candies

CandyDatabase also has:

String [] canonicalNames

which is a sorted array of canonical names of everything in tier2Candy, which is what is needed to add a CANDY_MATCH filter to persistence/ItemFinder for fuzzy matching candy.

- ASH $item proxy:

boolean ITEM.candy -> true if any candy

Effect data.

- ASH $effect proxy:

int EFFECT.candy_tier -> 0, 1, 2, 3

0 = not a candy synthesis effect
1 = simple, simple
2 = simple, complex
3 = complex, complex

- "checkcandy" command

Simply lists everything in CandyDatabase.tier0Candy

- "checkitems" command

When we see that the description says an item is a candy, allow "candy", "candy1" or "candy2".
ItemDatabase generates the "item line" for candy with candy, candy1, candy2, as appropriate

- "test newitem" (and hence ItemDatabase.registerItem)

For candy items, enter into CandyDatabase

The above has all the "data" we will need and exposes some of it to ASH

******Phase 2******

Using the skill.

- SynthesizeRequest does what is necessary to cast the skill and handle inventory.

- CLI commands in SynthesizeCommand:

These use fuzzy matching on "candy" items via ItemFinder's CANDY_MATCH filter.

synthesize CANDY1, CANDY2

"acquires" CANDY1 and CANDY2 and uses the skill, if acquisition succeeds

synthesize? CANDY1, CANDY2

tells you which effect this combination of candy will produce
and
for each of CANDY1, CANDY2:
-- how many are "easily accessible" (no mall or clan)
-- mall price
-- simulated result of "acquire": fail, use, pull from storage, take from closet, buy, whatever
and
result of attempting skill:
FAIL - you cannot acquire (at least) one candy
SUCCEED - and total "value" of the two ingredients, even if you use one or both from what you already own.

- ASH functions in RuntimeLibrary:

boolean candy_synthesis( item candy1, item candy2 )

Does retrieve_item() on candy1 and candy2, casts the skill, and returns true - or false, if failed to retrieve. The equivalent of the "synthesize" command.

effect candy_synthesis_result( item candy1, item candy2 )

The "simulated" result of doing the above - either the resulting effect, if it would succeed, or $effect[ none ] if retrieval would fail

This phase will allow people to use Ezandora's tool to explore options and then make it so via KoLmafia.

******Phase 3******

ASH support in RuntimeLibrary using internal functions in CandyDatabase:

item [int] candy_for_tier( int tier )

Returns an array of all candy in tier 1, 2, or 3 (or 0, if you want to spade). Note that "tier 1" is all "simple" candies and "tier 3" is all "complex" candies.
This will be ordered randomly.

You could do the following:

item [int] candy = candy_for_tier( 1 );
sort candy by -available_amount( value );
... to sort by high-to-low "easily available count"
sort candy by mall_price( value );
... to sort by low-to-high "mall price"

item [int] candy_synthesis_pairing( effect eff, item candy1 )

Returns an array of all candy that will synthesize with candy1 to produce eff. The array can be empty if you ask for a tier 1 effect and give it a complex candy or ask for a tier 3 effect and give it a simple candy.

This is probably all the ASH support needed to write a smart script which will get you the desired effect "cheaply".

******Phase 4******

A panel in the Item Manager to let you do this.

At the top:

3 rows of 5 buttons each: the Tier 1, Tier 2, and Tier 3 effects:

Beneath:

Two (blank) text panes: Candy A and Candy B

At the Right:

(Disable) "Synthesize!" button

Candy A
Have:
Cost:

Candy B:
Have:
Cost:

When you press one of the 15 Effect buttons, it highlights.
The Candy A pane fills with a table of candies, populated based on the Effect tier
Each row has three columns:
Name
Count
Cost

As is usual for such tables in KoLmafia, click on the column head to sort on that column

If you press another Effect button, the previous one unhighlights (and the table clears) and the new one highlights and replaces the Candy A table.

If you select a candy in the Candy A table, the Candy B table fills with a table of all candies that will synthesize with the selected candy to produce the desired effect. As expected, you can sort on the three columns there, two. Additionally, the Have and Cost fields in the right for Candy A will have numbers.

If you select a different candy in Candy A, the Candy B table and the Candy A data in the right change appropriately.

If you select a candy in Candy B, the Candy B values in the right are filled in and the Synthesize! button is enabled.
If you deselect the candy, the values are cleared and the button is disabled.

If you click on the Synthesize! button, it acquires Candy A and Candy B and synthesizes the desired effect.

******Phase 5******

Allow automatic generation of the effect, as requested:

CLI command:

synthesize EFFECT
synthesize? EFFECT

Use an algorithm to calculate the "cheapest" two candies to use to get the desired effect. And yes, some people will want to consider "candy in inventory" to be worth 0 and some will want to consider it to be worth the mall price. Same old controversy.

(Ezandora's script uses only candies in inventory if in Ronin or Hardcore and always buys from the mall otherwise. That's not a bad model.)

If we add "synthesize EFFECT" to the various effects in statuseffects.txt:

- "up EFFECT" uses that command
- Therefore, up arrows in the charpane will work
- You can put it in a mood
- You can use it with the maximizer

All of the above will have to be taught that it takes a spleen...

******
 
Last edited:

Veracity

Developer
Staff member
Revision 17612 does Phase 1 and half of Phase 3.

1) When we parse items.txt, "candy", "candy1", and "candy2" items are registered with CandyDatabase, which has data structures and methods that are useful elsewhere.

2) Items have a string candy_type proxy record field:

Code:
[color=green]> ash $item[ cool whip ].candy_type[/color]

Returned: none

[color=green]> ash $item[ hard rock candy ].candy_type[/color]

Returned: unspaded

[color=green]> ash $item[ Angry Farmer candy ].candy_type[/color]

Returned: simple

[color=green]> ash $item[ sugar sheet ].candy_type[/color]

Returned: complex

3) Effects have an int candy_tier proxy record field:

Code:
[color=green]> ash $effect[ Synthesis: Greed ].candy_tier[/color]

Returned: 3

[color=green]> ash $effect[ Synthesis: Pungent ].candy_tier[/color]

Returned: 1

[color=green]> ash $effect[ Synthesis: Smart ].candy_tier[/color]

Returned: 2

[color=green]> ash $effect[ Got Milk ].candy_tier[/color]

Returned: 0

4) ASH now has a function to return all the candy in a tier:

item [int] candy_for_tier( int tier )

Code:
[color=green]> ash candy_for_tier( 0 )[/color]

Returned: aggregate string [1]
0 => hard rock candy

[color=green]> ash candy_for_tier( 1 ).count()[/color]

Returned: 66

[color=green]> ash candy_for_tier( 2 ).count()[/color]

Returned: 214

[color=green]> ash candy_for_tier( 3 ).count()[/color]

Returned: 148

Note that this is not convenient to check if a given candy is in a tier; you can't say "candy_for_tier( 1 ) contains $item[ Angry Farmer candy ]", for example. Instead, you'd say "$item[ Angry Farmer candy ].candy_type == "simple"". This is an array that you can use with "sort by" to order by mall price, quantity on hand, or what have you.

5) The "checkcandy" command will list all unspaded candy (with no argument) or will tell you the candy type of the specified candies. (That last was primarily to be able to test the CANDY_MATCH filter):

Code:
[color=green]> checkcandy[/color]

***Unspaded candy: hard rock candy

[color=green]> checkcandy angry farmer candy, sugar sheet[/color]

Angry Farmer candy: simple
sugar sheet: complex

[color=green]> checkcandy cool whip[/color]

[color=red][cool whip] is not candy.[/color]

6) The "item string" generated by ItemDatabase now correctly includes "candy", "candy1", or "candy2", as appropriate.
 
Top