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.enumaction import EnumAction
|
||||||
from .objects.listaction import ListAction
|
from .objects.listaction import ListAction
|
||||||
from .solve import *
|
from .solve import *
|
||||||
|
from .read_char import *
|
||||||
|
|
||||||
|
|
||||||
parser = BoneMarketArgumentParser(
|
parser = BoneMarketArgumentParser(
|
||||||
prog='Bone Market Solver',
|
prog='Bone Market Solver',
|
||||||
@ -71,7 +73,7 @@ skeleton_parameters = parser.add_argument_group(
|
|||||||
skeleton_parameters.add_argument(
|
skeleton_parameters.add_argument(
|
||||||
"-s", "--shadowy",
|
"-s", "--shadowy",
|
||||||
type=int,
|
type=int,
|
||||||
required=True,
|
default=Char.SHADOWY.value,
|
||||||
help="the effective level of Shadowy used for selling to buyers",
|
help="the effective level of Shadowy used for selling to buyers",
|
||||||
dest='shadowy_level'
|
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 .costs import Cost
|
||||||
from ..objects.action import Action
|
from ..objects.action import Action
|
||||||
|
from ..read_char import Char
|
||||||
|
from ..challenge_functions import narrow_challenge, mean_outcome
|
||||||
|
|
||||||
|
|
||||||
class Adjustment(Enum):
|
class Adjustment(Enum):
|
||||||
"""An action that is taken after all parts have been added to a skeleton."""
|
"""An action that is taken after all parts have been added to a skeleton."""
|
||||||
|
|
||||||
CARVE_AWAY_AGE = Action(
|
CARVE_AWAY_AGE = Action(
|
||||||
"Carve away some evidence of age",
|
"Carve away some evidence of age",
|
||||||
cost = Cost.ACTION.value,
|
cost = Cost.ACTION.value / narrow_challenge(6, Char.MITHRIDACY.value),
|
||||||
antiquity = -2
|
antiquity = -2,
|
||||||
|
implausibility = mean_outcome(0, 2, narrow_challenge(6, Char.MITHRIDACY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
DISGUISE_AMALGAMY = Action(
|
DISGUISE_AMALGAMY = Action(
|
||||||
"Disguise the amalgamy of this piece",
|
"Disguise the amalgamy of this piece",
|
||||||
cost = Cost.ACTION.value + 25*Cost.JADE_FRAGMENT.value,
|
cost = 25*Cost.JADE_FRAGMENT.value + Cost.ACTION.value / narrow_challenge(6, Char.KATALEPTIC_TOXICOLOGY.value),
|
||||||
amalgamy = -2
|
amalgamy = -2,
|
||||||
|
implausibility = mean_outcome(0, 2, narrow_challenge(6, Char.KATALEPTIC_TOXICOLOGY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
MAKE_LESS_DREADFUL = Action(
|
MAKE_LESS_DREADFUL = Action(
|
||||||
"Make your skeleton less dreadful",
|
"Make your skeleton less dreadful",
|
||||||
cost = Cost.ACTION.value,
|
cost = Cost.ACTION.value / narrow_challenge(6, Char.KATALEPTIC_TOXICOLOGY.value),
|
||||||
menace = -2
|
menace = -2,
|
||||||
|
implausibility = mean_outcome(0, 2, narrow_challenge(6, Char.KATALEPTIC_TOXICOLOGY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -5,6 +5,9 @@ from enum import Enum
|
|||||||
|
|
||||||
from .costs import Cost
|
from .costs import Cost
|
||||||
from ..objects.action import Action
|
from ..objects.action import Action
|
||||||
|
from ..read_char import Char
|
||||||
|
from ..challenge_functions import narrow_challenge, broad_challenge, mean_outcome
|
||||||
|
|
||||||
|
|
||||||
class Appendage(Enum):
|
class Appendage(Enum):
|
||||||
"""An action that is taken once all skulls are added to a skeleton."""
|
"""An action that is taken once all skulls are added to a skeleton."""
|
||||||
@ -17,6 +20,7 @@ class Appendage(Enum):
|
|||||||
amalgamy = 2
|
amalgamy = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO: Difficulty is increased by 2 for each Fin or Tentacle on the skeleton
|
||||||
ALBATROSS_WING = Action(
|
ALBATROSS_WING = Action(
|
||||||
"Put an Albatross Wing on your (Skeleton Type)",
|
"Put an Albatross Wing on your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value + Cost.ALBATROSS_WING.value,
|
cost = Cost.ACTION.value + Cost.ALBATROSS_WING.value,
|
||||||
@ -26,6 +30,7 @@ class Appendage(Enum):
|
|||||||
amalgamy = 1
|
amalgamy = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO: Difficulty is increased by 2 for each Arm, Leg, Wing, and Tentacle that is already attached
|
||||||
AMBER_FIN = Action(
|
AMBER_FIN = Action(
|
||||||
"Attach the Amber-Crusted Fin to your (Skeleton Type)",
|
"Attach the Amber-Crusted Fin to your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value + Cost.AMBER_FIN.value,
|
cost = Cost.ACTION.value + Cost.AMBER_FIN.value,
|
||||||
@ -36,6 +41,7 @@ class Appendage(Enum):
|
|||||||
menace = 1
|
menace = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO: Difficulty is increased with Fins on the skeleton
|
||||||
BAT_WING = Action(
|
BAT_WING = Action(
|
||||||
"Add a Bat Wing to your (Skeleton Type)",
|
"Add a Bat Wing to your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value + Cost.BAT_WING.value,
|
cost = Cost.ACTION.value + Cost.BAT_WING.value,
|
||||||
@ -51,7 +57,7 @@ class Appendage(Enum):
|
|||||||
value = 50,
|
value = 50,
|
||||||
tails_needed = -1,
|
tails_needed = -1,
|
||||||
tails = 1,
|
tails = 1,
|
||||||
menace = 2
|
menace = mean_outcome(2, 1, narrow_challenge(4, Char.MONSTROUS_ANATOMY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
CRUSTACEAN_PINCER = Action(
|
CRUSTACEAN_PINCER = Action(
|
||||||
@ -80,6 +86,8 @@ class Appendage(Enum):
|
|||||||
legs = 1
|
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(
|
FIN_BONES = Action(
|
||||||
"Put Fins on your (Skeleton Type)",
|
"Put Fins on your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value + Cost.FIN_BONES.value,
|
cost = Cost.ACTION.value + Cost.FIN_BONES.value,
|
||||||
@ -94,7 +102,7 @@ class Appendage(Enum):
|
|||||||
value = 2750,
|
value = 2750,
|
||||||
limbs_needed = -1,
|
limbs_needed = -1,
|
||||||
arms = 1,
|
arms = 1,
|
||||||
antiquity = 2
|
antiquity = mean_outcome(2, 1, narrow_challenge(11, Char.MONSTROUS_ANATOMY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
HELICAL_THIGH = Action(
|
HELICAL_THIGH = Action(
|
||||||
@ -103,7 +111,7 @@ class Appendage(Enum):
|
|||||||
value = 300,
|
value = 300,
|
||||||
limbs_needed = -1,
|
limbs_needed = -1,
|
||||||
legs = 1,
|
legs = 1,
|
||||||
amalgamy = 2
|
amalgamy = mean_outcome(2, 1, narrow_challenge(6, Char.SHAPELING_ARTS.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
HUMAN_ARM = Action(
|
HUMAN_ARM = Action(
|
||||||
@ -120,7 +128,8 @@ class Appendage(Enum):
|
|||||||
cost = Cost.ACTION.value + Cost.IVORY_FEMUR.value,
|
cost = Cost.ACTION.value + Cost.IVORY_FEMUR.value,
|
||||||
value = 6500,
|
value = 6500,
|
||||||
limbs_needed = -1,
|
limbs_needed = -1,
|
||||||
legs = 1
|
legs = 1,
|
||||||
|
implausibility = mean_outcome(0, 4, narrow_challenge(7, Char.MONSTROUS_ANATOMY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
IVORY_HUMERUS = Action(
|
IVORY_HUMERUS = Action(
|
||||||
@ -128,9 +137,12 @@ class Appendage(Enum):
|
|||||||
cost = Cost.ACTION.value + Cost.IVORY_HUMERUS.value,
|
cost = Cost.ACTION.value + Cost.IVORY_HUMERUS.value,
|
||||||
value = 1500,
|
value = 1500,
|
||||||
limbs_needed = -1,
|
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(
|
JURASSIC_THIGH = Action(
|
||||||
"Apply a Jurassic Thigh Bone to your (Skeleton Type)",
|
"Apply a Jurassic Thigh Bone to your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value + Cost.JURASSIC_FEMUR.value,
|
cost = Cost.ACTION.value + Cost.JURASSIC_FEMUR.value,
|
||||||
@ -140,6 +152,8 @@ class Appendage(Enum):
|
|||||||
antiquity = 1
|
antiquity = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO: Base challenge: Narrow, Mithridacy 6
|
||||||
|
# Difficulty increases by 1 for each limb that is NOT a KNOTTED_HUMERUS
|
||||||
KNOTTED_HUMERUS = Action(
|
KNOTTED_HUMERUS = Action(
|
||||||
"Apply a Knotted Humerus to your (Skeleton Type)",
|
"Apply a Knotted Humerus to your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value + Cost.KNOTTED_HUMERUS.value,
|
cost = Cost.ACTION.value + Cost.KNOTTED_HUMERUS.value,
|
||||||
@ -149,6 +163,8 @@ class Appendage(Enum):
|
|||||||
amalgamy = 1
|
amalgamy = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO: Base challenge: Monstrous Anatomy 4
|
||||||
|
# No failure info on wiki
|
||||||
OBSIDIAN_TAIL = Action(
|
OBSIDIAN_TAIL = Action(
|
||||||
"Apply an Obsidian Chitin Tail to your (Skeleton Type)",
|
"Apply an Obsidian Chitin Tail to your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value + Cost.OBSIDIAN_TAIL.value,
|
cost = Cost.ACTION.value + Cost.OBSIDIAN_TAIL.value,
|
||||||
@ -164,9 +180,11 @@ class Appendage(Enum):
|
|||||||
value = 250,
|
value = 250,
|
||||||
tails_needed = -1,
|
tails_needed = -1,
|
||||||
tails = 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(
|
TERROR_BIRD_WING = Action(
|
||||||
"Add the Wing of a Young Terror Bird to your (Skeleton Type)",
|
"Add the Wing of a Young Terror Bird to your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value + Cost.TERROR_BIRD_WING.value,
|
cost = Cost.ACTION.value + Cost.TERROR_BIRD_WING.value,
|
||||||
@ -183,7 +201,7 @@ class Appendage(Enum):
|
|||||||
value = 250,
|
value = 250,
|
||||||
tails_needed = -1,
|
tails_needed = -1,
|
||||||
tails = 1,
|
tails = 1,
|
||||||
antiquity = 1
|
antiquity = mean_outcome(0, 1, narrow_challenge(4, Char.MONSTROUS_ANATOMY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
UNIDENTIFIED_THIGH = Action(
|
UNIDENTIFIED_THIGH = Action(
|
||||||
@ -194,27 +212,19 @@ class Appendage(Enum):
|
|||||||
legs = 1
|
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(
|
WITHERED_TENTACLE = Action(
|
||||||
"Put a Withered Tentacle on your (Skeleton Type)",
|
"Put a Withered Tentacle on your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value + Cost.WITHERED_TENTACLE.value,
|
cost = Cost.ACTION.value + Cost.WITHERED_TENTACLE.value,
|
||||||
value = 250,
|
value = 250,
|
||||||
limbs_needed = -1,
|
limbs_needed = -1,
|
||||||
tentacles = 1,
|
tentacles = 1,
|
||||||
antiquity = -1
|
antiquity = -1,
|
||||||
|
implausibility = mean_outcome(0, 2, narrow_challenge(5, Char.MONSTROUS_ANATOMY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
REMOVE_TAIL = Action(
|
REMOVE_TAIL = Action(
|
||||||
"Remove the tail from your (Skeleton Type)",
|
"Remove the tail from your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value,
|
cost = Cost.ACTION.value * 1 / broad_challenge(220, Char.DANGEROUS.value),
|
||||||
tails = -1
|
tails = -1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -5,6 +5,21 @@ from enum import Enum
|
|||||||
|
|
||||||
from .costs import Cost
|
from .costs import Cost
|
||||||
from ..objects.action import Action
|
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):
|
class Embellishment(Enum):
|
||||||
"""An action is taken after a declaration has been made for a skeleton."""
|
"""An action is taken after a declaration has been made for a skeleton."""
|
||||||
@ -17,7 +32,7 @@ class Embellishment(Enum):
|
|||||||
|
|
||||||
CONVINCING_HISTORY = Action(
|
CONVINCING_HISTORY = Action(
|
||||||
"Invest great time and skill in coming up with a convincing history",
|
"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
|
implausibility = -5
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -5,13 +5,15 @@ from enum import Enum
|
|||||||
|
|
||||||
from .costs import Cost
|
from .costs import Cost
|
||||||
from ..objects.action import Action
|
from ..objects.action import Action
|
||||||
|
from ..challenge_functions import narrow_challenge, mean_outcome
|
||||||
|
from ..read_char import Char
|
||||||
|
|
||||||
class Skull(Enum):
|
class Skull(Enum):
|
||||||
"""An action that is taken immediately after starting a skeleton."""
|
"""An action that is taken immediately after starting a skeleton."""
|
||||||
|
|
||||||
BAPTIST_SKULL = Action(
|
BAPTIST_SKULL = Action(
|
||||||
"Duplicate the skull of John the Baptist, if you can call that a skull",
|
"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,
|
value = 1250,
|
||||||
skulls_needed = -1,
|
skulls_needed = -1,
|
||||||
skulls = 1,
|
skulls = 1,
|
||||||
@ -20,13 +22,14 @@ class Skull(Enum):
|
|||||||
|
|
||||||
BRASS_SKULL = Action(
|
BRASS_SKULL = Action(
|
||||||
"Affix a Bright Brass Skull to your (Skeleton Type)",
|
"Affix a Bright Brass Skull to your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value + Cost.BRASS_SKULL.value + 200*Cost.NEVERCOLD_BRASS.value,
|
cost = Cost.ACTION.value + Cost.BRASS_SKULL.value + mean_outcome(200*Cost.NEVERCOLD_BRASS.value, 0, narrow_challenge(6, Char.MITHRIDACY.value)),
|
||||||
value = 6500,
|
value = mean_outcome(6500, 6000, narrow_challenge(6, Char.MITHRIDACY.value)),
|
||||||
skulls_needed = -1,
|
skulls_needed = -1,
|
||||||
skulls = 1,
|
skulls = 1,
|
||||||
implausibility = 2
|
implausibility = mean_outcome(2, 6, narrow_challenge(6, Char.MITHRIDACY.value)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO
|
||||||
CORAL_SKULL = Action(
|
CORAL_SKULL = Action(
|
||||||
"Affix a Skull in Coral to your (Skeleton Type)",
|
"Affix a Skull in Coral to your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value + Cost.CORAL_SKULL.value + Cost.SCINTILLACK.value,
|
cost = Cost.ACTION.value + Cost.CORAL_SKULL.value + Cost.SCINTILLACK.value,
|
||||||
@ -43,7 +46,7 @@ class Skull(Enum):
|
|||||||
skulls_needed = -1,
|
skulls_needed = -1,
|
||||||
skulls = 2,
|
skulls = 2,
|
||||||
amalgamy = 1,
|
amalgamy = 1,
|
||||||
antiquity = 2
|
antiquity = mean_outcome(2, 1, narrow_challenge(4, Char.MONSTROUS_ANATOMY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
# Adds Exhaustion
|
# Adds Exhaustion
|
||||||
@ -53,7 +56,8 @@ class Skull(Enum):
|
|||||||
value = 10000,
|
value = 10000,
|
||||||
skulls_needed = -1,
|
skulls_needed = -1,
|
||||||
skulls = 1,
|
skulls = 1,
|
||||||
exhaustion = 2
|
exhaustion = 2,
|
||||||
|
implausibility = mean_outcome(0, 2, narrow_challenge(4, Char.MITHRIDACY.value)),
|
||||||
)
|
)
|
||||||
|
|
||||||
EYELESS_SKULL = Action(
|
EYELESS_SKULL = Action(
|
||||||
@ -72,13 +76,13 @@ class Skull(Enum):
|
|||||||
skulls_needed = -1,
|
skulls_needed = -1,
|
||||||
skulls = 1,
|
skulls = 1,
|
||||||
antiquity = 1,
|
antiquity = 1,
|
||||||
menace = 2
|
menace = mean_outcome(2, 1, narrow_challenge(6, Char.MONSTROUS_ANATOMY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
# Seeking the Name of Mr. Eaten
|
# Seeking the Name of Mr. Eaten
|
||||||
OWN_SKULL = Action(
|
OWN_SKULL = Action(
|
||||||
"Duplicate your own skull and affix it here",
|
"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,
|
value = -250,
|
||||||
skulls_needed = -1,
|
skulls_needed = -1,
|
||||||
skulls = 1
|
skulls = 1
|
||||||
@ -100,7 +104,7 @@ class Skull(Enum):
|
|||||||
value = 2500,
|
value = 2500,
|
||||||
skulls_needed = -1,
|
skulls_needed = -1,
|
||||||
skulls = 1,
|
skulls = 1,
|
||||||
menace = 2
|
menace = mean_outcome(2, 1, narrow_challenge(4, Char.MONSTROUS_ANATOMY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
RUBBERY_SKULL = Action(
|
RUBBERY_SKULL = Action(
|
||||||
@ -119,19 +123,20 @@ class Skull(Enum):
|
|||||||
skulls_needed = -1,
|
skulls_needed = -1,
|
||||||
skulls = 1,
|
skulls = 1,
|
||||||
antiquity = 1,
|
antiquity = 1,
|
||||||
menace = 1
|
menace = mean_outcome(1, 0, narrow_challenge(6, Char.MONSTROUS_ANATOMY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
STYGIAN_IVORY = Action(
|
STYGIAN_IVORY = Action(
|
||||||
"Use a Carved Ball of Stygian Ivory to cap off your (Skeleton Type)",
|
"Use a Carved Ball of Stygian Ivory to cap off your (Skeleton Type)",
|
||||||
cost = Cost.ACTION.value + Cost.STYGIAN_IVORY.value,
|
cost = Cost.ACTION.value + Cost.STYGIAN_IVORY.value,
|
||||||
value = 250,
|
value = 250,
|
||||||
skulls_needed = -1
|
skulls_needed = -1,
|
||||||
|
implausibility = mean_outcome(0, 2, narrow_challenge(6, Char.MITHRIDACY.value))
|
||||||
)
|
)
|
||||||
|
|
||||||
VAKE_SKULL = Action(
|
VAKE_SKULL = Action(
|
||||||
"Duplicate the Vake's skull and use it to decorate your (Skeleton Type)",
|
"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,
|
value = 6500,
|
||||||
skulls_needed = -1,
|
skulls_needed = -1,
|
||||||
skulls = 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.
|
# This multiplier is applied to the profit margin to avoid losing precision due to rounding.
|
||||||
PROFIT_MARGIN_MULTIPLIER = 10000000
|
PROFIT_MARGIN_MULTIPLIER = 10000000
|
||||||
|
ATTRIBUTE_MULTIPLIER = 10000000
|
||||||
|
|
||||||
# This is the highest number of attribute to calculate fractional exponents for.
|
# This is the highest number of attribute to calculate fractional exponents for.
|
||||||
MAXIMUM_ATTRIBUTE = 100
|
MAXIMUM_ATTRIBUTE = 100
|
||||||
|
|
||||||
# This is a constant used to calculate difficulty checks. You almost certainly do not need to change this.
|
from .challenge_functions import DIFFICULTY_SCALER
|
||||||
DIFFICULTY_SCALER = 0.6
|
|
||||||
|
|
||||||
|
|
||||||
def NewIntermediateBoolVar(self, name, expression, domain):
|
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()]))
|
model.Add(tentacles == cp_model.LinearExpr.ScalProd(actions.values(), [action.value.tentacles for action in actions.keys()]))
|
||||||
|
|
||||||
# Amalgamy calculation
|
# 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')
|
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
|
# 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')
|
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
|
# 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')
|
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
|
# 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')
|
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
|
# Counter-church calculation
|
||||||
# Calculate amount of Counter-church from Holy Relics of the Thigh of Saint Fiacre
|
# 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)
|
model.Add(net_profit == total_revenue - cost)
|
||||||
|
|
||||||
# This is necessary to preserve some degree of precision after dividing
|
# 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])
|
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)
|
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)
|
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]))
|
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)
|
model.Add(profit_margin == absolute_profit_margin).OnlyEnforceIf(positive_net_profit)
|
||||||
|
Loading…
Reference in New Issue
Block a user