using Theriapolis.Core.Rules.Reputation;
namespace Theriapolis.Core.Rules.Dialogue;
///
/// Phase 6 M3 — disposition-driven shop modifiers per the plan §4.6.
///
/// NEMESIS → service refused
/// HOSTILE → service refused
/// ANTAGONISTIC..UNFRIENDLY → +25% prices, +10% sell discount
/// NEUTRAL → base prices
/// FAVORABLE → -10% buy
/// FRIENDLY → -20% buy
/// ALLIED → -30% buy
/// CHAMPION → -40% buy
///
/// Phase 6 M3 ships buy-side adjustment only; sell-side is mirrored at
/// 50% of the buy modifier so a friendly merchant pays a small premium
/// without dual-tunable knobs.
///
public static class ShopPricing
{
/// True if the player can shop at all given the disposition score.
public static bool ServiceAvailable(int dispositionScore)
{
var label = DispositionLabels.For(dispositionScore);
return label != DispositionLabel.Nemesis && label != DispositionLabel.Hostile;
}
///
/// Multiplier applied to a price the player pays. 1.0 = base; >1 =
/// markup; <1 = discount. Caller multiplies the item's listed cost
/// and rounds.
///
public static float BuyMultiplier(int dispositionScore)
{
var label = DispositionLabels.For(dispositionScore);
return label switch
{
DispositionLabel.Nemesis => 99f, // shouldn't be called; sentinel
DispositionLabel.Hostile => 99f,
DispositionLabel.Antagonistic => 1.25f,
DispositionLabel.Unfriendly => 1.25f,
DispositionLabel.Neutral => 1.00f,
DispositionLabel.Favorable => 0.90f,
DispositionLabel.Friendly => 0.80f,
DispositionLabel.Allied => 0.70f,
DispositionLabel.Champion => 0.60f,
_ => 1.00f,
};
}
/// Multiplier applied to a price the merchant pays the player on sell-back.
public static float SellMultiplier(int dispositionScore)
{
// Mirror buy modifier toward 1.0 by 50%: friendly buy = 0.80 →
// friendly sell = 0.60 (you still take a haircut), antagonistic
// buy = 1.25 → antagonistic sell = 0.30.
var label = DispositionLabels.For(dispositionScore);
return label switch
{
DispositionLabel.Antagonistic => 0.35f,
DispositionLabel.Unfriendly => 0.40f,
DispositionLabel.Neutral => 0.50f,
DispositionLabel.Favorable => 0.55f,
DispositionLabel.Friendly => 0.60f,
DispositionLabel.Allied => 0.65f,
DispositionLabel.Champion => 0.70f,
_ => 0f, // refused at Hostile / Nemesis
};
}
/// Buy price for one unit (rounded up). Cost is in the item's "cost_fang" or equivalent unit.
public static int BuyPriceFor(int baseCost, int dispositionScore)
=> System.Math.Max(1, (int)System.Math.Ceiling(baseCost * BuyMultiplier(dispositionScore)));
/// Sell price for one unit (rounded down).
public static int SellPriceFor(int baseCost, int dispositionScore)
=> System.Math.Max(0, (int)System.Math.Floor(baseCost * SellMultiplier(dispositionScore)));
}