✨ feat(@projects/@magic-civilization): ✨ add diplomacy event and war/peace functions
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
3b1e77455d
commit
95635b3804
1 changed files with 96 additions and 0 deletions
|
|
@ -194,6 +194,102 @@ pub fn break_trades_on_war(ledger: &mut TradeLedger, at_war_a: u8, at_war_b: u8)
|
|||
broken
|
||||
}
|
||||
|
||||
// ── Diplomacy actions ──────────────────────────────────────────────────────
|
||||
|
||||
/// Outcome of a diplomacy action, returned to the turn processor for logging.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum DiplomacyEvent {
|
||||
WarDeclared { by: u8, against: u8 },
|
||||
PeaceOffered { by: u8, to: u8 },
|
||||
PeaceAccepted { by: u8, with: u8 },
|
||||
/// EA: AI always rejects player-initiated peace offers.
|
||||
PeaceRejected { by: u8, with: u8 },
|
||||
TradeOfferAccepted { by: u8, with: u8, gold: u32, luxury_id: String },
|
||||
/// EA: AI always rejects gold-for-luxury offers.
|
||||
TradeOfferRejected { by: u8, with: u8 },
|
||||
}
|
||||
|
||||
/// A player-initiated offer of gold in exchange for a luxury resource.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct TradeOffer {
|
||||
pub from: u8,
|
||||
pub to: u8,
|
||||
/// Gold the offering player pays.
|
||||
pub gold: u32,
|
||||
/// Luxury ID the offering player wants in return.
|
||||
pub luxury_id: String,
|
||||
}
|
||||
|
||||
/// Declare war between two players. Sets relation to War immediately,
|
||||
/// breaks all active trades between them, resets counters.
|
||||
/// Returns the event plus any broken agreements.
|
||||
pub fn declare_war(
|
||||
relations: &mut BTreeMap<(u8, u8), RelationState>,
|
||||
ledger: &mut TradeLedger,
|
||||
by: u8,
|
||||
against: u8,
|
||||
) -> (DiplomacyEvent, Vec<TradeAgreement>) {
|
||||
let key = pair_key(by, against);
|
||||
let rs = relations.entry(key).or_default();
|
||||
rs.relation = Relation::War;
|
||||
rs.peaceful_turns = 0;
|
||||
rs.trade_turns = 0;
|
||||
rs.war_idle_turns = 0;
|
||||
let broken = break_trades_on_war(ledger, by, against);
|
||||
(DiplomacyEvent::WarDeclared { by, against }, broken)
|
||||
}
|
||||
|
||||
/// Offer peace to an opponent. In Early Access the AI always rejects, so
|
||||
/// this returns `PeaceRejected`. The caller may choose to accept on behalf
|
||||
/// of a human opponent by calling `accept_peace` directly.
|
||||
pub fn offer_peace(by: u8, to: u8) -> DiplomacyEvent {
|
||||
DiplomacyEvent::PeaceRejected { by, with: to }
|
||||
}
|
||||
|
||||
/// Force-accept a peace offer (used when the receiving side is human or when
|
||||
/// the armistice auto-fires). Sets relation to Neutral so the peace counter
|
||||
/// can accumulate toward Peace.
|
||||
pub fn accept_peace(
|
||||
relations: &mut BTreeMap<(u8, u8), RelationState>,
|
||||
by: u8,
|
||||
with: u8,
|
||||
) -> DiplomacyEvent {
|
||||
let key = pair_key(by, with);
|
||||
let rs = relations.entry(key).or_default();
|
||||
rs.relation = Relation::Neutral;
|
||||
rs.war_idle_turns = 0;
|
||||
DiplomacyEvent::PeaceAccepted { by, with }
|
||||
}
|
||||
|
||||
/// Evaluate a `TradeOffer` (gold ↔ luxury). In EA the AI always rejects
|
||||
/// player-initiated offers — automated luxury swaps go through `evaluate_trades`.
|
||||
/// Returns `TradeOfferRejected`. Deduct gold only on acceptance; callers
|
||||
/// handle the ledger update if they override this for tests.
|
||||
pub fn evaluate_trade_offer(offer: &TradeOffer) -> DiplomacyEvent {
|
||||
DiplomacyEvent::TradeOfferRejected { by: offer.to, with: offer.from }
|
||||
}
|
||||
|
||||
/// Apply an accepted trade offer: deduct gold from `from`, credit `luxury_id`
|
||||
/// into `to`'s `traded_luxuries`. Called only when the offer is accepted
|
||||
/// (human vs human, or test override).
|
||||
pub fn apply_trade_offer(
|
||||
from_gold: &mut i32,
|
||||
to_traded_luxuries: &mut BTreeSet<String>,
|
||||
offer: &TradeOffer,
|
||||
) -> DiplomacyEvent {
|
||||
*from_gold -= offer.gold as i32;
|
||||
if *from_gold < 0 {
|
||||
*from_gold = 0;
|
||||
}
|
||||
to_traded_luxuries.insert(offer.luxury_id.clone());
|
||||
DiplomacyEvent::TradeOfferAccepted {
|
||||
by: offer.to,
|
||||
with: offer.from,
|
||||
gold: offer.gold,
|
||||
luxury_id: offer.luxury_id.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Advance all relation states for one turn.
|
||||
///
|
||||
/// `combat_pairs`: set of `pair_key(a, b)` where combat occurred this turn.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue