魔药经济学:神秘的魔法药水商店

魔药经济学:神秘的魔法药水商店

评价数不足
Algorithm for perfectly balanced potions
由 NatsuFTryuu 制作
I like math and optimization problems (which is a pretty weird thing to like I admit), so I decided to apply my skills to this game. I created an algorithm in Mathematica that allows you to find the ingredients that are perfectly balanced. There is a list of ingredients (along with their magimin and trait values), a list of potions (along with their ratios of the various magimins). You need to specify the amount of ingredients your cauldron holds as well as its maximum magimin value and which potion you want to create. Having done that, with a simple "Control+A" and "Shift+Enter" it will provide you with the total value of the created potion as well as the ingredients and their number in order to create a perfectly balanced potion with your available ingredients and cauldron constraints. If it produces some weird numbers or no numbers at all, then you don't have the ingredients to create a perfectly balanced potion.

NOTE TO ANYBODY READING: The code has been updated. There are still ingredients missing, but now the code takes the traits under consideration. The traits take a value of 1 (the positive trait), -1 (the negative trait) and 0 (we don't care what it is). In the section "Chosen Potion and Trait Set" you can specify the traits you want and the algorithm will attempt to make what you want. It has been thoroughly tested and if it doesn't return a list of ingredients and numbers then you don't have the necessary ingredients.Once again, for anybody who's further along in the game and can use this algorithm feel free to fill it in yourself. It's quite easy and I've tried to make it user friendly, but if there are any questions, feel free to leave a comment and I'll try to get back to you ASAP.
   
奖励
收藏
已收藏
取消收藏
Algorithm (Part 1)
(*This is meant to run in Mathematica. For those who have it you presumably know how to use it. For those who don't, simply copy-paste this entire thing into it and change what you need to change. (The appropriate spots have been specified). Then simply select everything (Ctrl+A) and execute (Shift+Enter). For anybody who's interested, I hope this is helpful to you.*) Clear["Global`*"] (*Ingredients list*) (*Each ingredient is in the format of "name, magimins, traits". The \ magimins are defined in-game as A,B,C,D,E. E.g. the feyberry has 6 \ parts of magimin A and 0 of B,C,D,E*) ingredients = { {"feyberry", {6, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}, {"mandrake_root", {0, 6, 0, 0, 0}, {0, 0, 0, 0, 0}}, {"sack_of_slime", {0, 0, 6, 0, 0}, {0, 0, 0, 0, 0}}, {"pixiedust_diamond", {0, 4, 4, 0, 0}, {0, 0, 0, 0, 0}}, {"unicorn_horn", {0, 0, 8, 0, 0}, {-1, 0, 0, 0, 0}}, {"rotfly_larva", {0, 0, 4, 0, 0}, {1, 0, 0, 0, 0}}, {"river-pixie's_shell", {4, 4, 0, 0, 0}, {0, 0, 0, 0, 0}}, {"leech_snail's_shell", {12, 12, 0, 0, 0}, {0, 0, 0, 0, 0}}, {"horned_jelly", {18, 0, 0, 0, 0}, {0, -1, 0, 1,0}}, {"sphinx_flea", {12, 6, 0, 0, 0}, {0, 1, 0, 0, 0}}, {"kappa_pheromones", {4, 0, 4, 0, 0}, {0, 0, 0, 0, 0}}, {"cubic_ooze", {3, 3, 3, 0, 0}, {0, 0, 0, 0, 0}}, {"fairy_flower_bulb", {4, 0, 0, 0, 0}, {0, 0, 1, 0, 0}}, {"river_calamari", {8, 0, 0, 0, 0}, {0, -1, 0, 0, 0}}, {"glass_ore", {0, 0, 0, 18, 0}, {0, 0, 0, 0, 0}}, {"serpent's_slippery_tongue", {0, 8, 0, 0, 0}, {0, 0, -1, 0,0}}, {"rotfly_cocoon", {0, 0, 12, 0, 0}, {1, 0, 0, 0, 0}},{"sack_of_hive_slime", {0, 0, 18, 0, 0}, {0, 0, 0, 0,0}}, {"bog_beet", {0, 27, 0, 0, 0}, {-1, 0, 0, 0, 1}}, {"qilin's_tri_horn", {0, 0, 24, 0, 0}, {-1, 0, 0, 0, 0}}, {"bubble_ooze", {9, 9, 12, 12, 0}, {0, 0, 0, 0, 0}}, {"golem's_eye_diamond", {0, 12, 12, 0, 0}, {0, 0, 0, 0, 0}}, {"manwyrm_root", {0, 18, 0, 0, 0}, {0, 0, 0, 0, 0}}, {"figment_pomme", {0, 18, 6, 0, 0}, {0, 0, 0, 0, 0}}, {"golemite", {18, 12, 0, 10, 0}, {0, 0, 0, 0, 0}}, {"puckberry", {18, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}, {"warg_pheromones", {12, 0, 12, 0, 0}, {0, 0, 0, 0, 0}}, {"murkwater_pearl", {0, 0, 0, 12, 0}, {0, 0, 0, 1, 0}}, {"swamp_fish", {12, 0, 0, 6, 0}, {0, 0, 0, 0, 0}}, {"fairy_flower_bud", {12, 0, 0, 0, 0}, {0, 0, 1, 0, 0}}, {"impstool_mushroom", {0, 4, 0, 0, 0}, {0, 1, 0, 0, 0}}, {"mud_shrimp", {6, 0, 12, 0, 0}, {0, 0, 1, 0,0}}, {"desert_metal", {0, 12, 0, 0, 0}, {0, 1, 0, 0, 0}}, {"antlered_jelly", {30, 0, 0, 0, 0}, {0, -1, 0, 1, 0}}, {"static_spiderling", {0, 0, 0, 0, 30}, {0, 0, 0, -1, 1}}, {"cobweb_crayfish", {10, 0, 20, 0, 0}, {0, 0, 1, 0, 0}}, {"hallucinatory_shroom", {0, 0, 30, 0, 0}, {1, 0, 0, 0, -1}}, {"phantom_pomme", {0, 10, 30, 0, 0}, {1, 0, 0, 0, -1}}, {"mandragon_root", {0, 30, 0, 0, 0}, {0, 0, 0, 0, 0}}, {"barghast_canine", {0, 30, 0, 0, 10}, {0, 0, 0, 0, 0}}, {"spriggan_antler", {0, 0, 40, 0, 0}, {-1, 0, 0, 0, 0}}, {"mote_of_mana", {15, 15, 15, 15, 15}, {0, 0, 0, 0, 0}}, {"thunderbird's_molted_feather", {0, 0, 30, 0, 10}, {0, 0, 0, 0, 0}}, {"fire_flower", {40, 0, 0, 20, 0}, {0, 0, -1, 0, 0}}, {"fulgurite_ore", {0, 0, 0, 30, 0}, {0, 0, 0, 0, 0}}, {"slapping_turtle's_shell", {20, 20, 0, 0, 0}, {0, 0, 0, 0, 0}}, {"raiju_droppings", {0, 0, 30, 10, 0}, {0, 0, 0, 0, 0}}, {"thunder_quartz", {30, 10, 20, 0, 0}, {0, 0, 0, 0, 0}}, {"bogeyberry", {30, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}, {"saltwatermelon", {0, 0, 0, 40, 0}, {0, 0, 0, -1, 0}}, {"reef_radish", {0, 30, 0, 0, 0}, {-1, 0, 0, 0, 1}}, {"rotfly_adult", {0, 0, 20, 0, 0}, {1, 0, 0, 0, 0}}, {"malachite_ore", {30, 10, 0, 0, 20}, {0, 0, 0, 0, 0}}, {"sack_of_composite_slime", {0, 0, 30, 0, 0}, {0, 0, 0, 0, 0}}, {"dropsider's_shadow", {0, 0, 30, 20, 10}, {0, 0, 0, 0, 0}}, {"ghostlight_bloom", {18, 0, 0, 6, 0}, {0, 0, 0, 0, 0}}, {"squid_vine", {20, 20, 15, 0, 15}, {0, 0, 0, 0, 0}}, {"mosquito_plant", {10, 0, 20, 0, 30}, {0, 0, 0, 0, 0}}, {"fairy_flower_bloom", {20, 0, 0, 10, 0}, {0, 0, 1, 0, 0}}, {"spider's_bait_diamond", {0, 20, 20, 0, 0}, {0, 0, 0, 0, 0}}, {"sea_salt", {30, 0, 0, 0, 10}, {0, 0, 0, 0, 0}}, {"dwarf_kraken", {40, 0, 0, 0, 0}, {0, -1, 0, 0, 0}}, {"nessie_pheromones", {20, 0, 20, 0, 0}, {0, 0, 0, 0, 0}}, {"selkie_lice", {10, 20, 0, 0, 0}, {0, 1, 0, 0, 0}}, {"banshee's_bloody_tongue", {0, 40, 0, 0, 0}, {0, 0, -1, 0, 0}}, {"abyssalite", {30, 20, 0, 0, 10}, {0, 0, 0, 0, 0}}, {"giantstool_mushroom", {0, 20, 0, 0, 0}, {0, 1, 0, 0, 0}}, {"photonic_spore", {0, 10, 0, 30, 0}, {-1, 0, 1, 0, 0}}, {"miasma_spore", {0, 18, 0, 6, 0}, {0, 0, 0, 0, 0}}, {"shadowveil_pearl", {0, 0, 0, 20, 0}, {0, 0, 0, 1, 0}}, {"electrocution_eel", {10, 10, 10, 0, 0}, {0, 0, 0, 1, 0}}, {"copper_dollop", {15, 15, 15, 15, 0}, {0, 0, 0, 0, 0}}, {"shelled_pudding", {32, 0, 0, 32, 0}, {0, 0, 0, 0, 0}}, {"rock_salt", {24, 0, 0, 0, 8}, {1, 0, 0, 1, 0}}, {"watchdog_daisy", {0, 16, 0, 48, 0}, {0, 0, 0, 0, 0}}, {"owlbear_pheromones", {0, 0, 0, 0, 64}, {0, 0, -1, 0, 0}}, {"naga's_fang", {0, 48, 0, 0, 16}, {0, -1, 0, 0, 1}}, {"weeping_metal_ore", {0, 32, 64, 0, 0}, {0, -1, 0, 0, 0}}, {"sepulcher_widow", {0, 0, 0, 0, 48}, {0, 0, 0, -1, 1}}, {"crag_crab", {0, 0, 0, 0, 32}, {0, 0, 1, 0, 0}}, {"griffin's_whetstone_diamond", {0, 32, 32, 0, 0}, {0, 0, 0, 0, 0}}, {"medusa_spore", {0, 48, 0, 16, 0}, {-1, 0, 1, 0, 0}}, {"harpy's_heart_of_stone", {16, 0, 0, 32, 0}, {0, 1, 0, 0, 0}}, {"feathered_gelatin", {0, 0, 0, 48, 0}, {0, 1, -1, 0, 0}}, {"scimitar_crab's_shell", {32, 32, 0, 0, 0}, {0, 0, 0, 0, 0}}, {"sequined_custard", {0, 0, 32, 0, 16}, {0, 0, 0, 1, 0}}, {"swamp_octopus", {24, 0, 0, 0, 0}, {0, -1, 0, 0, 0}} }; MatrixForm[ingredients]; (*Potion list and ratios*) (*The ratio is interpreted as the proportios of each magimin. E.g. a \ health potion with a total value of 10, would need 5 of A, 5 of B and \ 0 from C,D,E to be considered an excellent potion*) potions = { {"health_potion", {1, 1, 0, 0, 0}}, {"mana_potion", {0, 1, 1, 0, 0}}, {"stamina_potion", {1, 0, 0, 0, 1}}, {"speed_potion", {0, 0, 1, 1, 0}}, {"fire_tonic", {1, 0, 1, 0, 0}}, {"ice_tonic", {1, 0, 0, 1, 0}}, {"thunder_tonic", {0, 1, 0, 1, 0}}, {"shadow_tonic", {0, 1, 0, 0, 1}}, {"sight_enhancer", {3, 4, 3, 0, 0}}, {"alertness_enhancer", {0, 3, 4, 3, 0}}, {"insight_enhancer", {4, 3, 0, 0, 3}}, {"dowsing_enhancer", {3, 0, 0, 3, 4}}, {"poison_cure", {2, 0, 1, 1, 0}}, {"drowsiness_cure", {1, 1, 0, 2, 0}}, {"petrification_cure", {1, 0, 2, 0, 1}}, {"silence_cure", {0, 2, 1, 0, 1}} }; MatrixForm[potions]; (*Cauldron constraints*) (*The size is how many ingredients can fit in cauldron, the maxValue \ is the total amount of magimins that fit in the cauldron*) cauldronSize = 8; cauldronMaxValue = 405; (*Chosen Potion and Trait set*) (*chosenPotion is the potion you want to make*) (*chosenTrait is what traits you want that potion to have. These are \ defined as 1="good", -1="bad" and 0="I don't care"*) chosenPotion = {"shadow_tonic", {0, 1, 0, 0, 1}}; chosenTrait = {0, 0, 1, 0, 1}; (*Ingredients for chosen potion*) (*These are the appropriate ingredients based on their magimins*) truthfulness = ConstantArray[False, {Length[ingredients], 5}]; For]], i++,
For[k = 1, k <= Length[ingredients], k++,
If[chosenPotion[[2]][[i]] != 0,
If[ingredients[[k, 2]][[i]] >= 0,
truthfulness[[k, i]] = True,
truthfulness[[k, i]] = False
],
If[ingredients[[k, 2]][[i]] != 0,
truthfulness[[k, i]] = False,
truthfulness[[k, i]] = True
]
];
];
];[/code]
Algorithm (Part 2)
acceptableIngredients = Array[0, {Length[ingredients], 3}]; For[j = 1, j <= Length[ingredients], j++, If[truthfulness[[j]] == {True, True, True, True, True}, acceptableIngredients[[j]] = {ingredients[[j, 1]], ingredients[[j, 2]], ingredients[[j, 3]]}, acceptableIngredients[[j]] = {0, 0, 0} ]; ]; MatrixForm[acceptableIngredients]; (*Trait constraint*) (*These are the appropriate ingredients based on their traits*) traitConstraints = ConstantArray[False, {Length[ingredients], Length[chosenTrait]}]; For, i++,
For[k = 1, k <= Length[ingredients], k++,
If[chosenTrait[[i]] == 1,
If[ingredients[[k, 3]][[i]] == 1 ||
ingredients[[k, 3]][[i]] == 0 ,
traitConstraints[[k, i]] = True,
False],
If[chosenTrait[[i]] == 0,
If[
ingredients[[k, 3]][[i]] == 1 ||
ingredients[[k, 3]][[i]] == 0 ||
ingredients[[k, 3]][[i]] == -1,
traitConstraints[[k, i]] = True],
If[chosenTrait[[i]] == -1,
If[
ingredients[[k, 3]][[i]] == -1 ||
ingredients[[k, 3]][[i]] == 0 ,
traitConstraints[[k, i]] = True,
False];
] ] ]; ]; ];

acceptableTraits = ConstantArray[0, Length[ingredients]];
For, i++,
If[traitConstraints[[i]] == {True, True, True, True, True},
acceptableTraits[[i]] = {True, True, True, True, True},
acceptableTraits[[i]] = {False, False, False, False, False}]
];

MatrixForm[acceptableTraits];

(*True ingredients*)
(*These are all the appropriate ingredients based on their magimins AND traits*)
trueIngredients = ConstantArray[0, {Length[ingredients], 3}];
For, i++,
If[acceptableIngredients[[i, 1]] != 0 &&
acceptableTraits[[i]] == {True, True, True, True, True},
trueIngredients[[i]] = {ingredients[[i, 1]], ingredients[[i, 2]],
ingredients[[i, 3]]},
trueIngredients[[i]] = {0, 0, {0, 0, 0, 0, 0}}
] ];

MatrixForm[trueIngredients];

(*These variables x represent the quantity of each \
ingredient in the final potion*)
variables = Array[x, Length[trueIngredients]];

In[163]:= (*Sum defines the total amount of each magimin category \
(A,B,C,D,E) in the final potion*)
sum = ConstantArray[0, 5];

For[j = 1, j <= 5, j++,
For, i++,
If[Total[trueIngredients[[i, 2]]] != 0,
sum[[j]] += trueIngredients[[i, 2]][[j]]*variables[[i]]
]; ]; ];

MatrixForm[sum];

(*These are the required ingredients, at least one which is needed to end up with a potion with the appropriate traits*)
(*Pos gives us the position of each of those required ingredients in \
the trueIngredients list*)
required = Array[0, Length[chosenTrait]];
posit = Array[0, Length[required]];
pos = Array[0, Length[required]];
For, i++,
If[chosenTrait[[i]] == 1,
required[[i]] =
Select[trueIngredients, #[[3]][[i]] == chosenTrait[[i]] &];
posit[[i]] =
Flatten[Position[trueIngredients, #] & /@ required[[i]]];
pos[[i]] = variables[[posit[[i]]]]
]; ];

MatrixForm[required];

MatrixForm[pos];


post = Array[1, Length[chosenTrait]];
For, i++,
If[Depth[pos[[i]]] == 2,
post[[i]] = 1,
post[[i]] = Total[pos[[i]]]
] ]

For, i++,
If[post[[i]] == 1,
post[[i]] = 1
] ];

MatrixForm[post];

(*Formulate the optimization problem*)
(*Here we define all the constraints of our problem*)
constraints = {
Total[Total[trueIngredients[[All, 2]]*variables]] <= cauldronMaxValue,
Total[variables] <= cauldronSize,
sum[[1]] <= (chosenPotion[[2]][[1]]/Total[chosenPotion[[2]]])*
Total[Total[trueIngredients[[All, 2]]*variables]],
sum[[2]] <= (chosenPotion[[2]][[2]]/Total[chosenPotion[[2]]])*
Total[Total[trueIngredients[[All, 2]]*variables]],
sum[[3]] <= (chosenPotion[[2]][[3]]/Total[chosenPotion[[2]]])*
Total[Total[trueIngredients[[All, 2]]*variables]],
sum[[4]] <= (chosenPotion[[2]][[4]]/Total[chosenPotion[[2]]])*
Total[Total[trueIngredients[[All, 2]]*variables]],
sum[[5]] <= (chosenPotion[[2]][[5]]/Total[chosenPotion[[2]]])*
Total[Total[trueIngredients[[All, 2]]*variables]],
post[[1]] >= 1,
post[[2]] >= 1,
post[[3]] >= 1,
post[[4]] >= 1,
post[[5]] >= 1,
variables \[Element] PositiveIntegers
};

(*Solve the optimization problem*)
solution = NMaximize[{Total[Total[trueIngredients[[All, 2]]*variables]],
constraints}, variables];

(*Display the result*)
ingredientQuantities = variables /. solution[[2]];

(*Extract the names of the ingredients needed for the potion*)
neededIngredients = Select[Transpose[{trueIngredients[[All, 1]],
ingredientQuantities}], #[[2]] > 0 &];

If[solution[[1]] >= 1 && solution[[1]] <= 60,
class = "minor",
If[solution[[1]] > 60 && solution[[1]] <= 150,
class = "common",
If[solution[[1]] > 150 && solution[[1]] <= 290,
class = "greater",
If[solution[[1]] > 290 && solution[[1]] <= 470,
class = "grand",
class = "masterwork"
] ] ] ];

If[AnyTrue[required, #[[All]] == {} &],
solution[[1]] = 0;
];

If[solution[[1]] > 0,
Print["The ingredients needed to make a '", class, " ",
chosenPotion[[1]], "' with a ", chosenTrait,
" trait set and a total value of ", solution[[1]], " are:"];
Print[neededIngredients];,
Print["There is no viable set of ingredients to create a perfectly \
balanced '", chosenPotion[[1]], "' with a ", chosenTrait,
" trait set."];
];
[/code]