From e2bb3fd0737845276cd04fea9e6b198b38c89eab Mon Sep 17 00:00:00 2001 From: TheTaques <35156969+TheTaques@users.noreply.github.com> Date: Tue, 24 Aug 2021 13:08:42 +0200 Subject: [PATCH 1/9] Add char file --- bonemarketsolver/__main__.py | 4 ++- bonemarketsolver/custom_char.py.template | 32 ++++++++++++++++++++++++ bonemarketsolver/default_char.py | 32 ++++++++++++++++++++++++ bonemarketsolver/read_char.py | 5 ++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 bonemarketsolver/custom_char.py.template create mode 100644 bonemarketsolver/default_char.py create mode 100644 bonemarketsolver/read_char.py diff --git a/bonemarketsolver/__main__.py b/bonemarketsolver/__main__.py index 039391e..954ed26 100644 --- a/bonemarketsolver/__main__.py +++ b/bonemarketsolver/__main__.py @@ -6,6 +6,8 @@ from .objects.bonemarketargumentparser import BoneMarketArgumentParser from .objects.enumaction import EnumAction from .objects.listaction import ListAction from .solve import * +from .read_char import * + parser = BoneMarketArgumentParser( prog='Bone Market Solver', @@ -71,7 +73,7 @@ skeleton_parameters = parser.add_argument_group( skeleton_parameters.add_argument( "-s", "--shadowy", type=int, - required=True, + default=Char.SHADOWY.value, help="the effective level of Shadowy used for selling to buyers", dest='shadowy_level' ) diff --git a/bonemarketsolver/custom_char.py.template b/bonemarketsolver/custom_char.py.template new file mode 100644 index 0000000..06b993a --- /dev/null +++ b/bonemarketsolver/custom_char.py.template @@ -0,0 +1,32 @@ +from enum import Enum + +class Char(Enum): + """Character stats""" + + SHADOWY = 300 + + DANGEROUS = 300 + + PERSUASIVE = 300 + + WATCHFUL = 300 + + PLAYER_OF_CHESS = 7 + + ARTISAN_OF_RED_SCIENCE = 7 + + GLASSWORK = 7 + + KATALEPTIC_TOXICOLOGY = 7 + + MITHRIDACY = 7 + + MONSTROUS_ANATOMY = 7 + + SHAPELING_ARTS = 7 + + BIZARRE = 15 + + DREADED = 15 + + RESPECTABLE = 15 diff --git a/bonemarketsolver/default_char.py b/bonemarketsolver/default_char.py new file mode 100644 index 0000000..06b993a --- /dev/null +++ b/bonemarketsolver/default_char.py @@ -0,0 +1,32 @@ +from enum import Enum + +class Char(Enum): + """Character stats""" + + SHADOWY = 300 + + DANGEROUS = 300 + + PERSUASIVE = 300 + + WATCHFUL = 300 + + PLAYER_OF_CHESS = 7 + + ARTISAN_OF_RED_SCIENCE = 7 + + GLASSWORK = 7 + + KATALEPTIC_TOXICOLOGY = 7 + + MITHRIDACY = 7 + + MONSTROUS_ANATOMY = 7 + + SHAPELING_ARTS = 7 + + BIZARRE = 15 + + DREADED = 15 + + RESPECTABLE = 15 diff --git a/bonemarketsolver/read_char.py b/bonemarketsolver/read_char.py new file mode 100644 index 0000000..4d23769 --- /dev/null +++ b/bonemarketsolver/read_char.py @@ -0,0 +1,5 @@ +try: + from .custom_char import * +except: + print("Note: custom_char.py does not exist. Using default_char.py") + from .default_char import * -- 2.45.2 From a86525324eff7cf5ca6c7d49a3b7256de09eb94a Mon Sep 17 00:00:00 2001 From: TheTaques <35156969+TheTaques@users.noreply.github.com> Date: Tue, 24 Aug 2021 13:10:39 +0200 Subject: [PATCH 2/9] Add support for fractions of skeleton attributes --- bonemarketsolver/solve.py | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/bonemarketsolver/solve.py b/bonemarketsolver/solve.py index 0aae1f5..65b42cf 100644 --- a/bonemarketsolver/solve.py +++ b/bonemarketsolver/solve.py @@ -22,6 +22,7 @@ from .data.torsos import Torso # This multiplier is applied to the profit margin to avoid losing precision due to rounding. PROFIT_MARGIN_MULTIPLIER = 10000000 +ATTRIBUTE_MULTIPLIER = 10000000 # This is the highest number of attribute to calculate fractional exponents for. MAXIMUM_ATTRIBUTE = 100 @@ -197,21 +198,36 @@ def Solve(shadowy_level, bone_market_fluctuations = None, zoological_mania = Non model.Add(tentacles == cp_model.LinearExpr.ScalProd(actions.values(), [action.value.tentacles for action in actions.keys()])) # Amalgamy calculation + multiplied_amalgamy = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, 'multiplied amalgamy') + model.Add(multiplied_amalgamy == cp_model.LinearExpr.ScalProd(actions.values(), [int(action.value.amalgamy*ATTRIBUTE_MULTIPLIER) for action in actions.keys()])) amalgamy = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, 'amalgamy') - model.Add(amalgamy == cp_model.LinearExpr.ScalProd(actions.values(), [action.value.amalgamy for action in actions.keys()])) + model.AddDivisionEquality(amalgamy, multiplied_amalgamy, ATTRIBUTE_MULTIPLIER) + + del multiplied_amalgamy # Antiquity calculation + multiplied_antiquity = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, 'multiplied antiquity') + model.Add(multiplied_antiquity == cp_model.LinearExpr.ScalProd(actions.values(), [int(action.value.antiquity*ATTRIBUTE_MULTIPLIER) for action in actions.keys()])) antiquity = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, 'antiquity') - model.Add(antiquity == cp_model.LinearExpr.ScalProd(actions.values(), [action.value.antiquity for action in actions.keys()])) + model.AddDivisionEquality(antiquity, multiplied_antiquity, ATTRIBUTE_MULTIPLIER) + + del multiplied_antiquity # Menace calculation + multiplied_menace = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, 'multiplied menace') + model.Add(multiplied_menace == cp_model.LinearExpr.ScalProd(actions.values(), [int(action.value.menace*ATTRIBUTE_MULTIPLIER) for action in actions.keys()])) menace = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, 'menace') - model.Add(menace == cp_model.LinearExpr.ScalProd(actions.values(), [action.value.menace for action in actions.keys()])) + model.AddDivisionEquality(menace, multiplied_menace, ATTRIBUTE_MULTIPLIER) + + del multiplied_menace # Implausibility calculation + multiplied_implausibility = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, 'multiplied implausibility') + model.Add(multiplied_implausibility == cp_model.LinearExpr.ScalProd(actions.values(), [int(action.value.implausibility*ATTRIBUTE_MULTIPLIER) for action in actions.keys()])) implausibility = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, 'implausibility') - model.Add(implausibility == cp_model.LinearExpr.ScalProd(actions.values(), [action.value.implausibility for action in actions.keys()])) + model.AddDivisionEquality(implausibility, multiplied_implausibility, ATTRIBUTE_MULTIPLIER) + del multiplied_implausibility # Counter-church calculation # Calculate amount of Counter-church from Holy Relics of the Thigh of Saint Fiacre @@ -1204,16 +1220,16 @@ def Solve(shadowy_level, bone_market_fluctuations = None, zoological_mania = Non model.Add(net_profit == total_revenue - cost) # This is necessary to preserve some degree of precision after dividing - multiplied_net_profit = model.NewIntVar(cp_model.INT32_MIN*PROFIT_MARGIN_MULTIPLIER, cp_model.INT32_MAX*PROFIT_MARGIN_MULTIPLIER, 'multiplied net profit') + multiplied_net_profit = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, 'multiplied net profit') model.AddMultiplicationEquality(multiplied_net_profit, [net_profit, PROFIT_MARGIN_MULTIPLIER]) - absolute_multiplied_net_profit = model.NewIntVar(0, cp_model.INT32_MAX*PROFIT_MARGIN_MULTIPLIER, 'absolute multiplied net profit') + absolute_multiplied_net_profit = model.NewIntVar(0, cp_model.INT32_MAX, 'absolute multiplied net profit') model.AddAbsEquality(absolute_multiplied_net_profit, multiplied_net_profit) - absolute_profit_margin = model.NewIntVar(cp_model.INT32_MIN*PROFIT_MARGIN_MULTIPLIER, cp_model.INT32_MAX*PROFIT_MARGIN_MULTIPLIER, 'absolute profit margin') + absolute_profit_margin = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, 'absolute profit margin') model.AddDivisionEquality(absolute_profit_margin, absolute_multiplied_net_profit, total_revenue) - profit_margin = model.NewIntVar(cp_model.INT32_MIN*PROFIT_MARGIN_MULTIPLIER, cp_model.INT32_MAX*PROFIT_MARGIN_MULTIPLIER, 'profit margin') + profit_margin = model.NewIntVar(cp_model.INT32_MIN, cp_model.INT32_MAX, 'profit margin') positive_net_profit = model.NewIntermediateBoolVar('positive net profit', net_profit, cp_model.Domain.FromFlatIntervals([0, cp_model.INT_MAX])) model.Add(profit_margin == absolute_profit_margin).OnlyEnforceIf(positive_net_profit) -- 2.45.2 From b002ca6e9620b3cd0edea8990327a43991efeeb7 Mon Sep 17 00:00:00 2001 From: TheTaques <35156969+TheTaques@users.noreply.github.com> Date: Tue, 24 Aug 2021 13:18:20 +0200 Subject: [PATCH 3/9] WIP: char stat adjusted skeleton actions --- bonemarketsolver/data/adjustments.py | 39 +++++++++++++++++++++---- bonemarketsolver/data/appendages.py | 17 ++++++++++- bonemarketsolver/data/embellishments.py | 27 ++++++++++++++++- 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/bonemarketsolver/data/adjustments.py b/bonemarketsolver/data/adjustments.py index 6d59d01..7fcba4e 100644 --- a/bonemarketsolver/data/adjustments.py +++ b/bonemarketsolver/data/adjustments.py @@ -5,26 +5,53 @@ from enum import Enum from .costs import Cost from ..objects.action import Action +from ..read_char import * + + +def _narrow_challenge_6(stat: int): + if 0 < stat < 11: + chance = stat/10 + elif stat < 1: + chance = .1 + else: + chance = 1 + + return chance + + +def _implausibility(stat: int): + chance = _narrow_challenge_6(stat) + + if chance == 1: + return 0 + else: + failure_actions = (1 / chance) - 1 + implausibility = 2 * failure_actions + return implausibility + class Adjustment(Enum): """An action that is taken after all parts have been added to a skeleton.""" CARVE_AWAY_AGE = Action( "Carve away some evidence of age", - cost = Cost.ACTION.value, - antiquity = -2 + cost = Cost.ACTION.value / _narrow_challenge_6(Char.MITHRIDACY.value), + antiquity = -2, + implausibility = _implausibility(Char.MITHRIDACY.value) ) DISGUISE_AMALGAMY = Action( "Disguise the amalgamy of this piece", - cost = Cost.ACTION.value + 25*Cost.JADE_FRAGMENT.value, - amalgamy = -2 + cost = 25*Cost.JADE_FRAGMENT.value + Cost.ACTION.value / _narrow_challenge_6(Char.KATALEPTIC_TOXICOLOGY.value), + amalgamy = -2, + implausibility = _implausibility(Char.KATALEPTIC_TOXICOLOGY.value) ) MAKE_LESS_DREADFUL = Action( "Make your skeleton less dreadful", - cost = Cost.ACTION.value, - menace = -2 + cost = Cost.ACTION.value / _narrow_challenge_6(Char.KATALEPTIC_TOXICOLOGY.value), + menace = -2, + implausibility = _implausibility(Char.KATALEPTIC_TOXICOLOGY.value) ) def __str__(self): diff --git a/bonemarketsolver/data/appendages.py b/bonemarketsolver/data/appendages.py index f235413..b9bba21 100644 --- a/bonemarketsolver/data/appendages.py +++ b/bonemarketsolver/data/appendages.py @@ -5,6 +5,18 @@ from enum import Enum from .costs import Cost from ..objects.action import Action +from ..read_char import * + + +def _narrow_challenge_4(stat: int): + stat += 2 + if stat < 8: + chance = stat/10 + else: + chance = 1 + + return chance + class Appendage(Enum): """An action that is taken once all skulls are added to a skeleton.""" @@ -17,6 +29,7 @@ class Appendage(Enum): amalgamy = 2 ) + # TODO: Difficulty is increased by 2 for each Fin or Tentacle on the skeleton ALBATROSS_WING = Action( "Put an Albatross Wing on your (Skeleton Type)", cost = Cost.ACTION.value + Cost.ALBATROSS_WING.value, @@ -26,6 +39,7 @@ class Appendage(Enum): amalgamy = 1 ) + # TODO: Difficulty is increased by 2 for each Arm, Leg, Wing, and Tentacle that is already attached AMBER_FIN = Action( "Attach the Amber-Crusted Fin to your (Skeleton Type)", cost = Cost.ACTION.value + Cost.AMBER_FIN.value, @@ -36,6 +50,7 @@ class Appendage(Enum): menace = 1 ) + # TODO: Difficulty is increased with Fins on the skeleton BAT_WING = Action( "Add a Bat Wing to your (Skeleton Type)", cost = Cost.ACTION.value + Cost.BAT_WING.value, @@ -51,7 +66,7 @@ class Appendage(Enum): value = 50, tails_needed = -1, tails = 1, - menace = 2 + menace = 2 * _narrow_challenge_4(Char.MONSTROUS_ANATOMY.value) + 1 * (1 - _narrow_challenge_4(Char.MONSTROUS_ANATOMY.value)) ) CRUSTACEAN_PINCER = Action( diff --git a/bonemarketsolver/data/embellishments.py b/bonemarketsolver/data/embellishments.py index 138e073..6b045b1 100644 --- a/bonemarketsolver/data/embellishments.py +++ b/bonemarketsolver/data/embellishments.py @@ -5,6 +5,31 @@ from enum import Enum from .costs import Cost from ..objects.action import Action +from ..read_char import * + + +def _narrow_challenge_6(stat: int): + if 0 < stat < 11: + chance = stat/10 + elif stat < 1: + chance = .1 + else: + chance = 1 + + return chance + + +def _convincing_history_cost(): + chance = _narrow_challenge_6(Char.KATALEPTIC_TOXICOLOGY.value) + + if chance == 1: + cost = 3*Cost.REVISIONIST_NARRATIVE.value + Cost.ACTION.value + else: + actions = 1 / chance + cost = actions * Cost.ACTION.value + cost += Cost.REVISIONIST_NARRATIVE.value * (3 + actions - 1) + return cost + class Embellishment(Enum): """An action is taken after a declaration has been made for a skeleton.""" @@ -17,7 +42,7 @@ class Embellishment(Enum): CONVINCING_HISTORY = Action( "Invest great time and skill in coming up with a convincing history", - cost = Cost.ACTION.value + 3*Cost.REVISIONIST_NARRATIVE.value, + cost = _convincing_history_cost(), implausibility = -5 ) -- 2.45.2 From 6df8cb461c587b3c51d45ad35be2bde93ebbe70a Mon Sep 17 00:00:00 2001 From: TheTaques <35156969+TheTaques@users.noreply.github.com> Date: Tue, 24 Aug 2021 13:18:20 +0200 Subject: [PATCH 4/9] WIP: char stat adjusted skeleton actions --- bonemarketsolver/challenge_functions.py | 17 +++++++++++ bonemarketsolver/data/adjustments.py | 39 +++++++++++++++++++++---- bonemarketsolver/data/appendages.py | 14 +++++++-- bonemarketsolver/data/embellishments.py | 17 ++++++++++- 4 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 bonemarketsolver/challenge_functions.py diff --git a/bonemarketsolver/challenge_functions.py b/bonemarketsolver/challenge_functions.py new file mode 100644 index 0000000..5759ece --- /dev/null +++ b/bonemarketsolver/challenge_functions.py @@ -0,0 +1,17 @@ +def narrow_challenge(difficulty_level: int, stat: int): + offset = 6 - difficulty_level + stat += offset + + if stat > 9: + return 1 + elif stat < 2: + return .1 + else: + return stat/10 + +def mean_outcome(success: int, failure: int, chance: float): + mean_success = success*chance + mean_failure = failure*(1-chance) + combined_mean_outcome = mean_success + mean_failure + + return combined_mean_outcome diff --git a/bonemarketsolver/data/adjustments.py b/bonemarketsolver/data/adjustments.py index 6d59d01..7fcba4e 100644 --- a/bonemarketsolver/data/adjustments.py +++ b/bonemarketsolver/data/adjustments.py @@ -5,26 +5,53 @@ from enum import Enum from .costs import Cost from ..objects.action import Action +from ..read_char import * + + +def _narrow_challenge_6(stat: int): + if 0 < stat < 11: + chance = stat/10 + elif stat < 1: + chance = .1 + else: + chance = 1 + + return chance + + +def _implausibility(stat: int): + chance = _narrow_challenge_6(stat) + + if chance == 1: + return 0 + else: + failure_actions = (1 / chance) - 1 + implausibility = 2 * failure_actions + return implausibility + class Adjustment(Enum): """An action that is taken after all parts have been added to a skeleton.""" CARVE_AWAY_AGE = Action( "Carve away some evidence of age", - cost = Cost.ACTION.value, - antiquity = -2 + cost = Cost.ACTION.value / _narrow_challenge_6(Char.MITHRIDACY.value), + antiquity = -2, + implausibility = _implausibility(Char.MITHRIDACY.value) ) DISGUISE_AMALGAMY = Action( "Disguise the amalgamy of this piece", - cost = Cost.ACTION.value + 25*Cost.JADE_FRAGMENT.value, - amalgamy = -2 + cost = 25*Cost.JADE_FRAGMENT.value + Cost.ACTION.value / _narrow_challenge_6(Char.KATALEPTIC_TOXICOLOGY.value), + amalgamy = -2, + implausibility = _implausibility(Char.KATALEPTIC_TOXICOLOGY.value) ) MAKE_LESS_DREADFUL = Action( "Make your skeleton less dreadful", - cost = Cost.ACTION.value, - menace = -2 + cost = Cost.ACTION.value / _narrow_challenge_6(Char.KATALEPTIC_TOXICOLOGY.value), + menace = -2, + implausibility = _implausibility(Char.KATALEPTIC_TOXICOLOGY.value) ) def __str__(self): diff --git a/bonemarketsolver/data/appendages.py b/bonemarketsolver/data/appendages.py index f235413..91fae0b 100644 --- a/bonemarketsolver/data/appendages.py +++ b/bonemarketsolver/data/appendages.py @@ -5,6 +5,9 @@ from enum import Enum from .costs import Cost from ..objects.action import Action +from ..read_char import * +from ..challenge_functions import narrow_challenge, mean_outcome + class Appendage(Enum): """An action that is taken once all skulls are added to a skeleton.""" @@ -17,6 +20,7 @@ class Appendage(Enum): amalgamy = 2 ) + # TODO: Difficulty is increased by 2 for each Fin or Tentacle on the skeleton ALBATROSS_WING = Action( "Put an Albatross Wing on your (Skeleton Type)", cost = Cost.ACTION.value + Cost.ALBATROSS_WING.value, @@ -26,6 +30,7 @@ class Appendage(Enum): amalgamy = 1 ) + # TODO: Difficulty is increased by 2 for each Arm, Leg, Wing, and Tentacle that is already attached AMBER_FIN = Action( "Attach the Amber-Crusted Fin to your (Skeleton Type)", cost = Cost.ACTION.value + Cost.AMBER_FIN.value, @@ -36,6 +41,7 @@ class Appendage(Enum): menace = 1 ) + # TODO: Difficulty is increased with Fins on the skeleton BAT_WING = Action( "Add a Bat Wing to your (Skeleton Type)", cost = Cost.ACTION.value + Cost.BAT_WING.value, @@ -51,7 +57,7 @@ class Appendage(Enum): value = 50, tails_needed = -1, tails = 1, - menace = 2 + menace = mean_outcome(2, 1, narrow_challenge(4, Char.MONSTROUS_ANATOMY.value)) ) CRUSTACEAN_PINCER = Action( @@ -80,6 +86,8 @@ class Appendage(Enum): legs = 1 ) + # TODO: Base challenge: Narrow, Monstrous Anatomy 1 + # The difficulty is increased by 2 for each Arm, Leg, Wing, and Tentacle already attached to your skeleton. FIN_BONES = Action( "Put Fins on your (Skeleton Type)", cost = Cost.ACTION.value + Cost.FIN_BONES.value, @@ -94,7 +102,7 @@ class Appendage(Enum): value = 2750, limbs_needed = -1, arms = 1, - antiquity = 2 + antiquity = mean_outcome(2, 1, narrow_challenge(11, Char.MONSTROUS_ANATOMY.value)) ) HELICAL_THIGH = Action( @@ -103,7 +111,7 @@ class Appendage(Enum): value = 300, limbs_needed = -1, legs = 1, - amalgamy = 2 + amalgamy = mean_outcome(2, 1, narrow_challenge(6, Char.SHAPELING_ARTS.value)) ) HUMAN_ARM = Action( diff --git a/bonemarketsolver/data/embellishments.py b/bonemarketsolver/data/embellishments.py index 138e073..99684a5 100644 --- a/bonemarketsolver/data/embellishments.py +++ b/bonemarketsolver/data/embellishments.py @@ -5,6 +5,21 @@ from enum import Enum from .costs import Cost from ..objects.action import Action +from ..read_char import * +from ..challenge_functions import narrow_challenge + + +def _convincing_history_cost(): + chance = narrow_challenge(6, Char.KATALEPTIC_TOXICOLOGY.value) + + if chance == 1: + cost = 3*Cost.REVISIONIST_NARRATIVE.value + Cost.ACTION.value + else: + actions = 1 / chance + cost = actions * Cost.ACTION.value + cost += Cost.REVISIONIST_NARRATIVE.value * (3 + actions - 1) + return cost + class Embellishment(Enum): """An action is taken after a declaration has been made for a skeleton.""" @@ -17,7 +32,7 @@ class Embellishment(Enum): CONVINCING_HISTORY = Action( "Invest great time and skill in coming up with a convincing history", - cost = Cost.ACTION.value + 3*Cost.REVISIONIST_NARRATIVE.value, + cost = _convincing_history_cost(), implausibility = -5 ) -- 2.45.2 From 6fedd6979facab8e06ba066b347dfe83e723e6ed Mon Sep 17 00:00:00 2001 From: TheTaques <35156969+TheTaques@users.noreply.github.com> Date: Tue, 24 Aug 2021 14:29:48 +0200 Subject: [PATCH 5/9] Move DIFFICULTY_SCALER to challenge_functions.py, specify char import in read_char.py --- bonemarketsolver/challenge_functions.py | 8 ++++++++ bonemarketsolver/read_char.py | 4 ++-- bonemarketsolver/solve.py | 3 +-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/bonemarketsolver/challenge_functions.py b/bonemarketsolver/challenge_functions.py index 5759ece..688b29d 100644 --- a/bonemarketsolver/challenge_functions.py +++ b/bonemarketsolver/challenge_functions.py @@ -1,3 +1,6 @@ +# This is a constant used to calculate difficulty checks. You almost certainly do not need to change this. +DIFFICULTY_SCALER = 0.6 + def narrow_challenge(difficulty_level: int, stat: int): offset = 6 - difficulty_level stat += offset @@ -9,6 +12,11 @@ def narrow_challenge(difficulty_level: int, stat: int): else: return stat/10 +def broad_challenge(difficulty_level: int, stat: int): + chance = DIFFICULTY_SCALER*stat//difficulty_level + + return chance + def mean_outcome(success: int, failure: int, chance: float): mean_success = success*chance mean_failure = failure*(1-chance) diff --git a/bonemarketsolver/read_char.py b/bonemarketsolver/read_char.py index 4d23769..8ddec3f 100644 --- a/bonemarketsolver/read_char.py +++ b/bonemarketsolver/read_char.py @@ -1,5 +1,5 @@ try: - from .custom_char import * + from .custom_char import Char except: print("Note: custom_char.py does not exist. Using default_char.py") - from .default_char import * + from .default_char import Char diff --git a/bonemarketsolver/solve.py b/bonemarketsolver/solve.py index 65b42cf..59305d5 100644 --- a/bonemarketsolver/solve.py +++ b/bonemarketsolver/solve.py @@ -27,8 +27,7 @@ ATTRIBUTE_MULTIPLIER = 10000000 # This is the highest number of attribute to calculate fractional exponents for. MAXIMUM_ATTRIBUTE = 100 -# This is a constant used to calculate difficulty checks. You almost certainly do not need to change this. -DIFFICULTY_SCALER = 0.6 +from .challenge_functions import DIFFICULTY_SCALER def NewIntermediateBoolVar(self, name, expression, domain): -- 2.45.2 From 515449addd724db4ed465cdf7bab33640b7f9486 Mon Sep 17 00:00:00 2001 From: TheTaques <35156969+TheTaques@users.noreply.github.com> Date: Tue, 24 Aug 2021 14:31:10 +0200 Subject: [PATCH 6/9] Use challenge functions, add further calculations --- bonemarketsolver/data/adjustments.py | 37 ++++++---------------------- bonemarketsolver/data/appendages.py | 36 ++++++++++++++------------- 2 files changed, 27 insertions(+), 46 deletions(-) diff --git a/bonemarketsolver/data/adjustments.py b/bonemarketsolver/data/adjustments.py index 7fcba4e..bfc7500 100644 --- a/bonemarketsolver/data/adjustments.py +++ b/bonemarketsolver/data/adjustments.py @@ -5,29 +5,8 @@ from enum import Enum from .costs import Cost from ..objects.action import Action -from ..read_char import * - - -def _narrow_challenge_6(stat: int): - if 0 < stat < 11: - chance = stat/10 - elif stat < 1: - chance = .1 - else: - chance = 1 - - return chance - - -def _implausibility(stat: int): - chance = _narrow_challenge_6(stat) - - if chance == 1: - return 0 - else: - failure_actions = (1 / chance) - 1 - implausibility = 2 * failure_actions - return implausibility +from ..read_char import Char +from ..challenge_functions import narrow_challenge, mean_outcome class Adjustment(Enum): @@ -35,23 +14,23 @@ class Adjustment(Enum): CARVE_AWAY_AGE = Action( "Carve away some evidence of age", - cost = Cost.ACTION.value / _narrow_challenge_6(Char.MITHRIDACY.value), + cost = Cost.ACTION.value / narrow_challenge(6, Char.MITHRIDACY.value), antiquity = -2, - implausibility = _implausibility(Char.MITHRIDACY.value) + implausibility = mean_outcome(0, 2, narrow_challenge(6, Char.MITHRIDACY.value)) ) DISGUISE_AMALGAMY = Action( "Disguise the amalgamy of this piece", - cost = 25*Cost.JADE_FRAGMENT.value + Cost.ACTION.value / _narrow_challenge_6(Char.KATALEPTIC_TOXICOLOGY.value), + cost = 25*Cost.JADE_FRAGMENT.value + Cost.ACTION.value / narrow_challenge(6, Char.KATALEPTIC_TOXICOLOGY.value), amalgamy = -2, - implausibility = _implausibility(Char.KATALEPTIC_TOXICOLOGY.value) + implausibility = mean_outcome(0, 2, narrow_challenge(6, Char.KATALEPTIC_TOXICOLOGY.value)) ) MAKE_LESS_DREADFUL = Action( "Make your skeleton less dreadful", - cost = Cost.ACTION.value / _narrow_challenge_6(Char.KATALEPTIC_TOXICOLOGY.value), + cost = Cost.ACTION.value / narrow_challenge(6, Char.KATALEPTIC_TOXICOLOGY.value), menace = -2, - implausibility = _implausibility(Char.KATALEPTIC_TOXICOLOGY.value) + implausibility = mean_outcome(0, 2, narrow_challenge(6, Char.KATALEPTIC_TOXICOLOGY.value)) ) def __str__(self): diff --git a/bonemarketsolver/data/appendages.py b/bonemarketsolver/data/appendages.py index 91fae0b..4c29475 100644 --- a/bonemarketsolver/data/appendages.py +++ b/bonemarketsolver/data/appendages.py @@ -5,8 +5,8 @@ from enum import Enum from .costs import Cost from ..objects.action import Action -from ..read_char import * -from ..challenge_functions import narrow_challenge, mean_outcome +from ..read_char import Char +from ..challenge_functions import narrow_challenge, broad_challenge, mean_outcome class Appendage(Enum): @@ -128,7 +128,8 @@ class Appendage(Enum): cost = Cost.ACTION.value + Cost.IVORY_FEMUR.value, value = 6500, limbs_needed = -1, - legs = 1 + legs = 1, + implausibility = mean_outcome(0, 4, narrow_challenge(7, Char.MONSTROUS_ANATOMY.value)) ) IVORY_HUMERUS = Action( @@ -136,9 +137,12 @@ class Appendage(Enum): cost = Cost.ACTION.value + Cost.IVORY_HUMERUS.value, value = 1500, limbs_needed = -1, - arms = 1 + arms = 1, + implausibility = mean_outcome(0, 2, narrow_challenge(6, Char.KATALEPTIC_TOXICOLOGY.value)) ) + # TODO: Base challenge: Narrow, Mithridacy 1 + # Difficulty increases by 2 for each Fin or Tentacle already attached to your skeleton. JURASSIC_THIGH = Action( "Apply a Jurassic Thigh Bone to your (Skeleton Type)", cost = Cost.ACTION.value + Cost.JURASSIC_FEMUR.value, @@ -148,6 +152,8 @@ class Appendage(Enum): antiquity = 1 ) + # TODO: Base challenge: Narrow, Mithridacy 6 + # Difficulty increases by 1 for each limb that is NOT a KNOTTED_HUMERUS KNOTTED_HUMERUS = Action( "Apply a Knotted Humerus to your (Skeleton Type)", cost = Cost.ACTION.value + Cost.KNOTTED_HUMERUS.value, @@ -157,6 +163,8 @@ class Appendage(Enum): amalgamy = 1 ) + # TODO: Base challenge: Monstrous Anatomy 4 + # No failure info on wiki OBSIDIAN_TAIL = Action( "Apply an Obsidian Chitin Tail to your (Skeleton Type)", cost = Cost.ACTION.value + Cost.OBSIDIAN_TAIL.value, @@ -172,9 +180,11 @@ class Appendage(Enum): value = 250, tails_needed = -1, tails = 1, - implausibility = 1 + implausibility = mean_outcome(1, 4, narrow_challenge(4, Char.MITHRIDACY.value)) ) + # TODO: Base challenge: Narrow, Monstrous Anatomy 1 + # Difficulty increases by 2 for each Fin already attached to your skeleton. TERROR_BIRD_WING = Action( "Add the Wing of a Young Terror Bird to your (Skeleton Type)", cost = Cost.ACTION.value + Cost.TERROR_BIRD_WING.value, @@ -191,7 +201,7 @@ class Appendage(Enum): value = 250, tails_needed = -1, tails = 1, - antiquity = 1 + antiquity = mean_outcome(0, 1, narrow_challenge(4, Char.MONSTROUS_ANATOMY.value)) ) UNIDENTIFIED_THIGH = Action( @@ -202,27 +212,19 @@ class Appendage(Enum): legs = 1 ) - WITHERED_TAIL = Action( - "Apply a Withered Tentacle as a tail on your (Skeleton Type)", - cost = Cost.ACTION.value + Cost.WITHERED_TENTACLE.value, - value = 250, - tails_needed = -1, - tails = 1, - antiquity = -1 - ) - WITHERED_TENTACLE = Action( "Put a Withered Tentacle on your (Skeleton Type)", cost = Cost.ACTION.value + Cost.WITHERED_TENTACLE.value, value = 250, limbs_needed = -1, tentacles = 1, - antiquity = -1 + antiquity = -1, + implausibility = mean_outcome(0, 2, narrow_challenge(5, Char.MONSTROUS_ANATOMY.value)) ) REMOVE_TAIL = Action( "Remove the tail from your (Skeleton Type)", - cost = Cost.ACTION.value, + cost = Cost.ACTION.value * 1 / broad_challenge(220, Char.DANGEROUS.value), tails = -1 ) -- 2.45.2 From d2ac78bb5dec94052f3256388e218536a97ea61e Mon Sep 17 00:00:00 2001 From: TheTaques <35156969+TheTaques@users.noreply.github.com> Date: Tue, 24 Aug 2021 14:40:18 +0200 Subject: [PATCH 7/9] Fix broad_challenge calculation --- bonemarketsolver/challenge_functions.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bonemarketsolver/challenge_functions.py b/bonemarketsolver/challenge_functions.py index 688b29d..cb025ce 100644 --- a/bonemarketsolver/challenge_functions.py +++ b/bonemarketsolver/challenge_functions.py @@ -13,7 +13,9 @@ def narrow_challenge(difficulty_level: int, stat: int): return stat/10 def broad_challenge(difficulty_level: int, stat: int): - chance = DIFFICULTY_SCALER*stat//difficulty_level + chance = DIFFICULTY_SCALER*stat/difficulty_level * 100 + chance = chance // 1 + chance /= 100 return chance -- 2.45.2 From ef254926b571db57e51ec26706a4d43d1e539b9c Mon Sep 17 00:00:00 2001 From: TheTaques <35156969+TheTaques@users.noreply.github.com> Date: Wed, 25 Aug 2021 15:58:32 +0200 Subject: [PATCH 8/9] Skull calculations --- bonemarketsolver/data/skulls.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/bonemarketsolver/data/skulls.py b/bonemarketsolver/data/skulls.py index d01a763..db46546 100644 --- a/bonemarketsolver/data/skulls.py +++ b/bonemarketsolver/data/skulls.py @@ -5,13 +5,15 @@ from enum import Enum from .costs import Cost from ..objects.action import Action +from ..challenge_functions import narrow_challenge, mean_outcome +from ..read_char import Char class Skull(Enum): """An action that is taken immediately after starting a skeleton.""" BAPTIST_SKULL = Action( "Duplicate the skull of John the Baptist, if you can call that a skull", - cost = Cost.ACTION.value + 500*Cost.BONE_FRAGMENT.value + 10*Cost.PEPPERCAPS.value, + cost = Cost.ACTION.value * 1 / narrow_challenge(6, Char.ARTISAN_OF_RED_SCIENCE.value) + 500*Cost.BONE_FRAGMENT.value + 10*Cost.PEPPERCAPS.value, value = 1250, skulls_needed = -1, skulls = 1, @@ -20,13 +22,14 @@ class Skull(Enum): BRASS_SKULL = Action( "Affix a Bright Brass Skull to your (Skeleton Type)", - cost = Cost.ACTION.value + Cost.BRASS_SKULL.value + 200*Cost.NEVERCOLD_BRASS.value, - value = 6500, + cost = Cost.ACTION.value + Cost.BRASS_SKULL.value + mean_outcome(200*Cost.NEVERCOLD_BRASS.value, 0, narrow_challenge(6, Char.MITHRIDACY.value)), + value = mean_outcome(6500, 6000, narrow_challenge(6, Char.MITHRIDACY.value)), skulls_needed = -1, skulls = 1, - implausibility = 2 + implausibility = mean_outcome(2, 6, narrow_challenge(6, Char.MITHRIDACY.value)), ) + # TODO CORAL_SKULL = Action( "Affix a Skull in Coral to your (Skeleton Type)", cost = Cost.ACTION.value + Cost.CORAL_SKULL.value + Cost.SCINTILLACK.value, @@ -43,7 +46,7 @@ class Skull(Enum): skulls_needed = -1, skulls = 2, amalgamy = 1, - antiquity = 2 + antiquity = mean_outcome(2, 1, narrow_challenge(4, Char.MONSTROUS_ANATOMY.value)) ) # Adds Exhaustion @@ -53,7 +56,8 @@ class Skull(Enum): value = 10000, skulls_needed = -1, skulls = 1, - exhaustion = 2 + exhaustion = 2, + implausibility = mean_outcome(0, 2, narrow_challenge(4, Char.MITHRIDACY.value)), ) EYELESS_SKULL = Action( @@ -72,13 +76,13 @@ class Skull(Enum): skulls_needed = -1, skulls = 1, antiquity = 1, - menace = 2 + menace = mean_outcome(2, 1, narrow_challenge(6, Char.MONSTROUS_ANATOMY.value)) ) # Seeking the Name of Mr. Eaten OWN_SKULL = Action( "Duplicate your own skull and affix it here", - cost = Cost.ACTION.value + 1000*Cost.BONE_FRAGMENT.value, + cost = Cost.ACTION.value * 1 / narrow_challenge(6, Char.ARTISAN_OF_RED_SCIENCE.value) + 1000*Cost.BONE_FRAGMENT.value, value = -250, skulls_needed = -1, skulls = 1 @@ -100,7 +104,7 @@ class Skull(Enum): value = 2500, skulls_needed = -1, skulls = 1, - menace = 2 + menace = mean_outcome(2, 1, narrow_challenge(4, Char.MONSTROUS_ANATOMY.value)) ) RUBBERY_SKULL = Action( @@ -119,19 +123,20 @@ class Skull(Enum): skulls_needed = -1, skulls = 1, antiquity = 1, - menace = 1 + menace = mean_outcome(1, 0, narrow_challenge(6, Char.MONSTROUS_ANATOMY.value)) ) STYGIAN_IVORY = Action( "Use a Carved Ball of Stygian Ivory to cap off your (Skeleton Type)", cost = Cost.ACTION.value + Cost.STYGIAN_IVORY.value, value = 250, - skulls_needed = -1 + skulls_needed = -1, + implausibility = mean_outcome(0, 2, narrow_challenge(6, Char.MITHRIDACY.value)) ) VAKE_SKULL = Action( "Duplicate the Vake's skull and use it to decorate your (Skeleton Type)", - cost = Cost.ACTION.value + 6000*Cost.BONE_FRAGMENT.value, + cost = Cost.ACTION.value + 6000*Cost.BONE_FRAGMENT.value + mean_outcome(0, Cost.ACTION.value + 300*Cost.BONE_FRAGMENT.value, narrow_challenge(6, Char.ARTISAN_OF_RED_SCIENCE.value)), value = 6500, skulls_needed = -1, skulls = 1, -- 2.45.2 From 3baaeae7c4e53ec7347dbc0d54205e24652ce7a5 Mon Sep 17 00:00:00 2001 From: TheTaques <35156969+TheTaques@users.noreply.github.com> Date: Fri, 27 Aug 2021 14:07:46 +0200 Subject: [PATCH 9/9] Fix non integer error --- bonemarketsolver/challenge_functions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bonemarketsolver/challenge_functions.py b/bonemarketsolver/challenge_functions.py index cb025ce..534e291 100644 --- a/bonemarketsolver/challenge_functions.py +++ b/bonemarketsolver/challenge_functions.py @@ -24,4 +24,4 @@ def mean_outcome(success: int, failure: int, chance: float): mean_failure = failure*(1-chance) combined_mean_outcome = mean_success + mean_failure - return combined_mean_outcome + return int(combined_mean_outcome) -- 2.45.2