feat: Implement support for Segmented Ribcage
Segmented Ribcages may be used in several unique ways, including a special scaling cost that necessitated the bulk of the code changes.
This commit is contained in:
commit
92e734d5d2
|
@ -19,6 +19,17 @@ class Appendage(Enum):
|
|||
amalgamy = 2
|
||||
)
|
||||
|
||||
# Cost from this scales with segments and is partially implemented separately
|
||||
# Requires Torso Style 110
|
||||
# Requires initial tail slot
|
||||
SEGMENTED_RIBCAGE = Action(
|
||||
"Extend the tail end with another Segmented Ribcage",
|
||||
cost = Cost.ACTION.value + Cost.SEGMENTED_RIBCAGE.value,
|
||||
value = 250,
|
||||
limbs_needed = 2,
|
||||
segments = 1
|
||||
)
|
||||
|
||||
ALBATROSS_WING = Action(
|
||||
"Put an Albatross Wing on your (Skeleton Type)",
|
||||
cost = Cost.ACTION.value + Cost.ALBATROSS_WING.value,
|
||||
|
|
|
@ -184,6 +184,10 @@ class Cost(Enum):
|
|||
# Khan's Heart, disgruntled academic
|
||||
SEARING_ENIGMA = 2*ACTION + 130*INFILTRATING + 2*INTERCEPTED_CABLEGRAM
|
||||
|
||||
# Segmented Ribcage
|
||||
# No consistent source
|
||||
SEGMENTED_RIBCAGE = cp_model.INT32_MAX/4
|
||||
|
||||
# Carved Ball of Stygian Ivory
|
||||
STYGIAN_IVORY = 250
|
||||
|
||||
|
|
|
@ -124,6 +124,16 @@ class Skull(Enum):
|
|||
menace = 1
|
||||
)
|
||||
|
||||
# Requires Torso Style 110
|
||||
SEGMENTED_RIBCAGE = Action(
|
||||
'Affix a Segmented Ribcage as the "skull"',
|
||||
cost = Cost.ACTION.value + Cost.SEGMENTED_RIBCAGE.value,
|
||||
value = 250,
|
||||
skulls_needed = -1,
|
||||
limbs_needed = 4,
|
||||
segments = 1
|
||||
)
|
||||
|
||||
STYGIAN_IVORY = Action(
|
||||
"Use a Carved Ball of Stygian Ivory to cap off your (Skeleton Type)",
|
||||
cost = Cost.ACTION.value + Cost.STYGIAN_IVORY.value,
|
||||
|
|
|
@ -134,5 +134,16 @@ class Torso(Enum):
|
|||
menace = 1
|
||||
)
|
||||
|
||||
SEGMENTED_RIBCAGE = Action(
|
||||
"Build on a Segmented Ribcage",
|
||||
cost = Cost.ACTION.value + Cost.SEGMENTED_RIBCAGE.value,
|
||||
torso_style = 110,
|
||||
value = 250,
|
||||
skulls_needed = 1,
|
||||
limbs_needed = 2,
|
||||
tails_needed = 1,
|
||||
segments = 1,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.value)
|
||||
|
|
|
@ -47,6 +47,9 @@ class Action:
|
|||
# Skeleton: Fins
|
||||
fins: int = 0
|
||||
|
||||
# Skeleton: Number of Segments
|
||||
segments: int = 0
|
||||
|
||||
# Skeleton: Tentacles
|
||||
tentacles: int = 0
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ __all__ = ['Adjustment', 'Appendage', 'Buyer', 'Declaration', 'DiplomatFascinati
|
|||
__author__ = "Jeremy Saklad"
|
||||
|
||||
from functools import partialmethod
|
||||
from itertools import chain
|
||||
from itertools import chain, repeat
|
||||
from os import cpu_count
|
||||
|
||||
from ortools.sat.python import cp_model
|
||||
|
@ -167,6 +167,10 @@ def Solve(shadowy_level, bone_market_fluctuations = None, zoological_mania = Non
|
|||
fins = model.NewIntVar('fins', lb = 0)
|
||||
model.Add(fins == cp_model.LinearExpr.WeightedSum(actions.values(), [action.value.fins for action in actions.keys()]))
|
||||
|
||||
# Segments calculation
|
||||
segments = model.NewIntVar('segments', lb = 0)
|
||||
model.Add(segments == cp_model.LinearExpr.WeightedSum(actions.values(), [action.value.segments for action in actions.keys()]))
|
||||
|
||||
# Tentacles calculation
|
||||
tentacles = model.NewIntVar('tentacles', lb = 0)
|
||||
model.Add(tentacles == cp_model.LinearExpr.WeightedSum(actions.values(), [action.value.tentacles for action in actions.keys()]))
|
||||
|
@ -326,10 +330,139 @@ def Solve(shadowy_level, bone_market_fluctuations = None, zoological_mania = Non
|
|||
del add_joints, add_joints_amber_cost_multiple
|
||||
|
||||
|
||||
cost = model.NewIntVar('cost', lb = 0, ub = maximum_cost)
|
||||
model.Add(cost == cp_model.LinearExpr.WeightedSum(actions.values(), [int(action.value.cost) for action in actions.keys()]) + add_joints_amber_cost + sale_cost)
|
||||
# Calculate cost of adding segments.
|
||||
# This is a partial sum formula.
|
||||
add_segments_brass_cost = model.NewIntVar('add segments brass cost', lb = 0)
|
||||
|
||||
del sale_cost, add_joints_amber_cost
|
||||
add_segments = actions[Appendage.SEGMENTED_RIBCAGE]
|
||||
|
||||
# Additional segments may be added once the torso and skulls are chosen, so the sum of their properties are the starting point.
|
||||
base_segments = model.NewIntVar('base segments', lb = 0)
|
||||
model.Add(base_segments == cp_model.LinearExpr.WeightedSum([value for (key, value) in actions.items() if isinstance(key, (Torso, Skull))], [action.value.segments for action in chain(Torso, Skull)]))
|
||||
|
||||
first_term, *_ = model.NewIntermediateIntVar(
|
||||
partialmethod(BoneMarketModel.AddMultiplicationEquality,
|
||||
variables=(
|
||||
25,
|
||||
*repeat(add_segments, 4),
|
||||
)
|
||||
),
|
||||
'add segments brass cost multiple first term'
|
||||
)
|
||||
|
||||
second_term, *_ = model.NewIntermediateIntVar(
|
||||
partialmethod(BoneMarketModel.AddMultiplicationEquality,
|
||||
variables=(
|
||||
100,
|
||||
*repeat(add_segments, 3),
|
||||
base_segments,
|
||||
)
|
||||
),
|
||||
'add segments brass cost multiple second term'
|
||||
)
|
||||
|
||||
third_term, *_ = model.NewIntermediateIntVar(
|
||||
partialmethod(BoneMarketModel.AddMultiplicationEquality,
|
||||
variables=(
|
||||
50,
|
||||
*repeat(add_segments, 3),
|
||||
)
|
||||
),
|
||||
'add segments brass cost multiple third term'
|
||||
)
|
||||
|
||||
fourth_term, *_ = model.NewIntermediateIntVar(
|
||||
partialmethod(BoneMarketModel.AddMultiplicationEquality,
|
||||
variables=(
|
||||
150,
|
||||
*repeat(add_segments, 2),
|
||||
*repeat(base_segments, 2),
|
||||
)
|
||||
),
|
||||
'add segments brass cost multiple fourth term'
|
||||
)
|
||||
|
||||
fifth_term, *_ = model.NewIntermediateIntVar(
|
||||
partialmethod(BoneMarketModel.AddMultiplicationEquality,
|
||||
variables=(
|
||||
150,
|
||||
*repeat(add_segments, 2),
|
||||
base_segments,
|
||||
)
|
||||
),
|
||||
'add segments brass cost multiple fifth term'
|
||||
)
|
||||
|
||||
sixth_term, *_ = model.NewIntermediateIntVar(
|
||||
partialmethod(BoneMarketModel.AddMultiplicationEquality,
|
||||
variables=(
|
||||
25,
|
||||
*repeat(add_segments, 2),
|
||||
)
|
||||
),
|
||||
'add segments brass cost multiple sixth term'
|
||||
)
|
||||
|
||||
seventh_term, *_ = model.NewIntermediateIntVar(
|
||||
partialmethod(BoneMarketModel.AddMultiplicationEquality,
|
||||
variables=(
|
||||
100,
|
||||
add_segments,
|
||||
*repeat(base_segments, 3),
|
||||
)
|
||||
),
|
||||
'add segments brass cost multiple seventh term'
|
||||
)
|
||||
|
||||
eighth_term, *_ = model.NewIntermediateIntVar(
|
||||
partialmethod(BoneMarketModel.AddMultiplicationEquality,
|
||||
variables=(
|
||||
150,
|
||||
add_segments,
|
||||
*repeat(base_segments, 2),
|
||||
)
|
||||
),
|
||||
'add segments brass cost multiple eighth term'
|
||||
)
|
||||
|
||||
ninth_term, *_ = model.NewIntermediateIntVar(
|
||||
partialmethod(BoneMarketModel.AddMultiplicationEquality,
|
||||
variables=(
|
||||
50,
|
||||
add_segments,
|
||||
base_segments,
|
||||
)
|
||||
),
|
||||
'add segments brass cost multiple ninth term'
|
||||
)
|
||||
|
||||
add_segments_brass_cost_multiple, *_ = model.NewIntermediateIntVar(
|
||||
partialmethod(BoneMarketModel.AddDivisionEquality,
|
||||
num=first_term + second_term + third_term + fourth_term + fifth_term + sixth_term + seventh_term + eighth_term + ninth_term,
|
||||
denom=2
|
||||
),
|
||||
'add segments brass cost multiple'
|
||||
)
|
||||
|
||||
del first_term, second_term, third_term, fourth_term, fifth_term, sixth_term, seventh_term, eighth_term, ninth_term
|
||||
|
||||
add_segments_brass_cost, *_ = model.NewIntermediateIntVar(
|
||||
partialmethod(BoneMarketModel.AddMultiplicationEquality,
|
||||
variables=(
|
||||
add_segments_brass_cost_multiple,
|
||||
Cost.NEVERCOLD_BRASS.value,
|
||||
)
|
||||
),
|
||||
'add segments brass cost'
|
||||
)
|
||||
|
||||
del add_segments, base_segments, add_segments_brass_cost_multiple
|
||||
|
||||
|
||||
cost = model.NewIntVar('cost', lb = 0, ub = maximum_cost)
|
||||
model.Add(cost == cp_model.LinearExpr.WeightedSum(actions.values(), [int(action.value.cost) for action in actions.keys()]) + add_joints_amber_cost + add_segments_brass_cost + sale_cost)
|
||||
|
||||
del sale_cost, add_joints_amber_cost, add_segments_brass_cost
|
||||
|
||||
|
||||
# Type of skeleton
|
||||
|
@ -443,6 +576,20 @@ def Solve(shadowy_level, bone_market_fluctuations = None, zoological_mania = Non
|
|||
.OnlyEnforceIf(actions[Declaration.CURATOR])
|
||||
|
||||
|
||||
# Skull requirements
|
||||
|
||||
model.Add(torso_style == 110) \
|
||||
.OnlyEnforceIf(model.BoolExpression(actions[Skull.SEGMENTED_RIBCAGE] > 0))
|
||||
|
||||
|
||||
# Appendage requirements
|
||||
|
||||
model.AddIf(model.BoolExpression(actions[Appendage.SEGMENTED_RIBCAGE] > 0),
|
||||
torso_style == 110,
|
||||
cp_model.LinearExpr.WeightedSum([value for (key, value) in actions.items() if isinstance(key, (Torso, Skull))], [action.value.tails_needed for action in chain(Torso, Skull)]) >= 1,
|
||||
)
|
||||
|
||||
|
||||
# Declaration requirements
|
||||
|
||||
model.AddIf(actions[Declaration.HUMANOID],
|
||||
|
|
Loading…
Reference in New Issue