WIP: Add character file and stat adjusted skeleton actions #2
@ -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'
|
||||
)
|
||||
|
27
bonemarketsolver/challenge_functions.py
Normal file
27
bonemarketsolver/challenge_functions.py
Normal file
@ -0,0 +1,27 @@
|
||||
# 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
|
||||
|
||||
if stat > 9:
|
||||
return 1
|
||||
elif stat < 2:
|
||||
return .1
|
||||
else:
|
||||
return stat/10
|
||||
|
||||
def broad_challenge(difficulty_level: int, stat: int):
|
||||
chance = DIFFICULTY_SCALER*stat/difficulty_level * 100
|
||||
chance = chance // 1
|
||||
chance /= 100
|
||||
|
||||
return chance
|
||||
|
||||
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 int(combined_mean_outcome)
|
32
bonemarketsolver/custom_char.py.template
Normal file
32
bonemarketsolver/custom_char.py.template
Normal file
@ -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
|
@ -5,26 +5,32 @@ from enum import Enum
|
||||
|
||||
from .costs import Cost
|
||||
from ..objects.action import Action
|
||||
from ..read_char import Char
|
||||
from ..challenge_functions import narrow_challenge, mean_outcome
|
||||
|
||||
|
||||
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 = mean_outcome(0, 2, narrow_challenge(6, 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 = mean_outcome(0, 2, narrow_challenge(6, 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 = mean_outcome(0, 2, narrow_challenge(6, Char.KATALEPTIC_TOXICOLOGY.value))
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
|
@ -5,6 +5,9 @@ from enum import Enum
|
||||
|
||||
from .costs import Cost
|
||||
from ..objects.action import Action
|
||||
from ..read_char import Char
|
||||
from ..challenge_functions import narrow_challenge, broad_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(
|
||||
@ -120,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(
|
||||
@ -128,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,
|
||||
@ -140,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,
|
||||
@ -149,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,
|
||||
@ -164,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,
|
||||
@ -183,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(
|
||||
@ -194,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
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
)
|
||||
|
||||
|
@ -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,
|
||||
|
32
bonemarketsolver/default_char.py
Normal file
32
bonemarketsolver/default_char.py
Normal file
@ -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
|
5
bonemarketsolver/read_char.py
Normal file
5
bonemarketsolver/read_char.py
Normal file
@ -0,0 +1,5 @@
|
||||
try:
|
||||
from .custom_char import Char
|
||||
except:
|
||||
print("Note: custom_char.py does not exist. Using default_char.py")
|
||||
from .default_char import Char
|
@ -22,12 +22,12 @@ 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
|
||||
|
||||
# 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):
|
||||
@ -197,21 +197,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
|
||||
@ -1235,16 +1250,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)
|
||||
|
Loading…
Reference in New Issue
Block a user