Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 15 additions & 16 deletions crates/engine/src/database/synthesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8329,8 +8329,8 @@ fn is_bloodthirst_x_etb_replacement(replacement: &ReplacementDefinition) -> bool
///
/// Counter-count linkage: the ranged `EffectZoneChoice` Sacrifice completion
/// stamps `state.last_effect_count` (the number of creatures chosen).
/// `QuantityRef::EventContextAmount`'s resolver falls back through
/// `last_effect_count`, so the `PutCounter` count reads exactly the number
/// `QuantityRef::PreviousEffectCount` reads that continuation-local tally
/// directly, so an enclosing trigger's scalar amount cannot shadow the number
/// sacrificed. For Devour N > 1 the count is wrapped in
/// `QuantityExpr::Multiply { factor: n, .. }` (CR 702.82a "N counters per
/// creature sacrificed"). `PreviousEffectAmount` is NOT used — it reads
Expand Down Expand Up @@ -8418,19 +8418,19 @@ pub fn synthesize_devour(face: &mut CardFace) {
let quality_noun = type_filter_noun(quality, false);
let quality_noun_plural = type_filter_noun(quality, true);

// CR 122.1: N +1/+1 counters per creature sacrificed this way. The
// per-creature count is `EventContextAmount` (resolves to the number
// the ranged Sacrifice choice stamped into `last_effect_count`); for
// CR 702.82a / CR 702.82c: N +1/+1 counters per sacrificed permanent. The
// per-sacrifice count is `PreviousEffectCount` (the number the ranged
// Sacrifice choice stamped into `last_effect_count`); for
// N > 1 it is scaled by `factor: n`.
let counter_count = if n == 1 {
QuantityExpr::Ref {
qty: QuantityRef::EventContextAmount,
qty: QuantityRef::PreviousEffectCount,
}
} else {
QuantityExpr::Multiply {
factor: n as i32,
inner: Box::new(QuantityExpr::Ref {
qty: QuantityRef::EventContextAmount,
qty: QuantityRef::PreviousEffectCount,
}),
}
};
Expand Down Expand Up @@ -8497,7 +8497,7 @@ pub fn synthesize_devour(face: &mut CardFace) {
///
/// `expected_n` is load-bearing: a card carrying both a printed enters-with-K
/// replacement and `Keyword::Devour { n: N≠K, .. }` must not dedupe — the
/// `Multiply` factor (N) for N > 1 and the bare `EventContextAmount` (N == 1)
/// `Multiply` factor (N) for N > 1 and the bare `PreviousEffectCount` (N == 1)
/// discriminate the count.
///
/// `expected_quality` is equally load-bearing (CR 702.82c): a land-quality Devour
Expand Down Expand Up @@ -8545,13 +8545,13 @@ fn is_devour_etb_replacement(
}
let expected_count = if expected_n == 1 {
QuantityExpr::Ref {
qty: QuantityRef::EventContextAmount,
qty: QuantityRef::PreviousEffectCount,
}
} else {
QuantityExpr::Multiply {
factor: expected_n as i32,
inner: Box::new(QuantityExpr::Ref {
qty: QuantityRef::EventContextAmount,
qty: QuantityRef::PreviousEffectCount,
}),
}
};
Expand Down Expand Up @@ -22582,7 +22582,7 @@ mod devour_synthesis_tests {

/// CR 702.82a: Devour 1 synthesizes one `Moved`/`SelfRef` replacement
/// whose execute chain is `Sacrifice(UpTo) → PutCounter(P1P1, SelfRef)`,
/// and whose `PutCounter` count is the bare `EventContextAmount` (one
/// and whose `PutCounter` count is the bare `PreviousEffectCount` (one
/// counter per creature sacrificed).
#[test]
fn synthesize_devour_1_builds_sacrifice_then_counter_chain() {
Expand Down Expand Up @@ -22629,7 +22629,7 @@ mod devour_synthesis_tests {
"Devour sacrifices creatures the controller controls"
);

// Sub-ability: PutCounter of EventContextAmount P1P1 counters on self.
// Sub-ability: PutCounter of PreviousEffectCount P1P1 counters on self.
let sub = execute
.sub_ability
.as_deref()
Expand All @@ -22647,11 +22647,10 @@ mod devour_synthesis_tests {
assert_eq!(
*count,
QuantityExpr::Ref {
qty: QuantityRef::EventContextAmount
qty: QuantityRef::PreviousEffectCount
},
"Devour 1 places exactly one counter per creature sacrificed — \
the count must be the bare EventContextAmount (NOT \
PreviousEffectAmount, which the ranged Sacrifice never stamps)"
the count must be the direct continuation-local PreviousEffectCount"
);
}

Expand Down Expand Up @@ -22680,7 +22679,7 @@ mod devour_synthesis_tests {
QuantityExpr::Multiply {
factor: 2,
inner: Box::new(QuantityExpr::Ref {
qty: QuantityRef::EventContextAmount
qty: QuantityRef::PreviousEffectCount
}),
},
"Devour 2 places 2 counters per creature sacrificed (CR 702.82a)"
Expand Down
2 changes: 2 additions & 0 deletions crates/engine/src/game/ability_rw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2110,6 +2110,7 @@ fn legacy_quantity_ref(x: &QuantityRef) -> bool {
| QuantityRef::TrackedSetAggregate { .. }
| QuantityRef::ExiledFromHandThisResolution
| QuantityRef::PreviousEffectAmount { .. }
| QuantityRef::PreviousEffectCount
| QuantityRef::TurnsTaken
| QuantityRef::CrimesCommittedThisTurn
| QuantityRef::ChosenNumber
Expand Down Expand Up @@ -6125,6 +6126,7 @@ fn rw_quantity_ref(x: &QuantityRef) -> RwProfile {
// (member-invariant under uniformity).
QuantityRef::ExiledFromHandThisResolution
| QuantityRef::PreviousEffectAmount { .. }
| QuantityRef::PreviousEffectCount
| QuantityRef::TurnsTaken
| QuantityRef::CrimesCommittedThisTurn
| QuantityRef::AttackedThisTurn { .. }
Expand Down
1 change: 1 addition & 0 deletions crates/engine/src/game/ability_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2170,6 +2170,7 @@ fn scan_quantity_ref(x: &QuantityRef, mode: ScanMode) -> Axes {
},
QuantityRef::ExiledFromHandThisResolution => Axes::NONE,
QuantityRef::PreviousEffectAmount { .. } => Axes::NONE,
QuantityRef::PreviousEffectCount => Axes::NONE,
QuantityRef::LifeLostThisTurn { player } => {
let mut acc = Axes {
event: false,
Expand Down
2 changes: 2 additions & 0 deletions crates/engine/src/game/coverage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1586,6 +1586,7 @@ fn fmt_quantity_ref(qty: &QuantityRef) -> String {
}
QuantityRef::VoteCount { choice_index } => format!("# of votes for choice {choice_index}"),
QuantityRef::PreviousEffectAmount { .. } => "amount from preceding effect".into(),
QuantityRef::PreviousEffectCount => "count from preceding effect".into(),
QuantityRef::TrackedSetSize => "cards moved".into(),
QuantityRef::FilteredTrackedSetSize { filter, .. } => {
format!("filtered tracked set ({})", fmt_target(filter))
Expand Down Expand Up @@ -8235,6 +8236,7 @@ fn quantity_ref_feature(qref: &QuantityRef) -> (&'static str, FeatureSupport) {
QuantityRef::DistinctCounterKindsAmong { .. } => ("DistinctCounterKindsAmong", Handled),
QuantityRef::VoteCount { .. } => ("VoteCount", Handled),
QuantityRef::PreviousEffectAmount { .. } => ("PreviousEffectAmount", Handled),
QuantityRef::PreviousEffectCount => ("PreviousEffectCount", Handled),
QuantityRef::TrackedSetSize => ("TrackedSetSize", Handled),
QuantityRef::FilteredTrackedSetSize { .. } => ("FilteredTrackedSetSize", Handled),
QuantityRef::TrackedSetAggregate { .. } => ("TrackedSetAggregate", Handled),
Expand Down
1 change: 1 addition & 0 deletions crates/engine/src/game/effects/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3409,6 +3409,7 @@ fn quantity_ref_counts_population_matching(
| QuantityRef::TrackedSetAggregate { .. }
| QuantityRef::ExiledFromHandThisResolution
| QuantityRef::PreviousEffectAmount { .. }
| QuantityRef::PreviousEffectCount
| QuantityRef::LifeLostThisTurn { .. }
| QuantityRef::PartySize { .. }
| QuantityRef::UnspentMana { .. }
Expand Down
8 changes: 5 additions & 3 deletions crates/engine/src/game/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19012,9 +19012,11 @@ mod stage2_injector_tests {
// Identity re-established, not assumed: `9869a19f28c791ee`,
// `2bc316e3aa0297f8`, `8df98486627bfe15` at the new coordinates — the same
// three digests this log has carried since the first merge.
"game/effects/mod.rs:7002".to_string(),
"game/effects/mod.rs:7079".to_string(),
"game/effects/mod.rs:10317".to_string(),
// `PreviousEffectCount` classification adds one line above all three producers,
// so they move uniformly to `:7003/:7080/:10318`; no prompt site changes.
"game/effects/mod.rs:7003".to_string(),
"game/effects/mod.rs:7080".to_string(),
"game/effects/mod.rs:10318".to_string(),
// UNMOVED across the rebase, and that is itself evidence the SET did not
// move: a census that had gained or lost a producer would not leave this
// entry both byte-identical AND at the same coordinate.
Expand Down
2 changes: 2 additions & 0 deletions crates/engine/src/game/layers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2906,6 +2906,7 @@ fn quantity_ref_reads_zone(qty: &QuantityRef, zone: Zone) -> bool {
| QuantityRef::TrackedSetAggregate { .. }
| QuantityRef::ExiledFromHandThisResolution
| QuantityRef::PreviousEffectAmount { .. }
| QuantityRef::PreviousEffectCount
| QuantityRef::LifeLostThisTurn { .. }
| QuantityRef::Speed { .. }
| QuantityRef::EventContextAmount
Expand Down Expand Up @@ -3234,6 +3235,7 @@ fn quantity_ref_reads_life(qty: &QuantityRef) -> bool {
| QuantityRef::TrackedSetAggregate { .. }
| QuantityRef::ExiledFromHandThisResolution
| QuantityRef::PreviousEffectAmount { .. }
| QuantityRef::PreviousEffectCount
| QuantityRef::PartySize { .. }
| QuantityRef::UnspentMana { .. }
| QuantityRef::Speed { .. }
Expand Down
7 changes: 7 additions & 0 deletions crates/engine/src/game/quantity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,7 @@ fn quantity_ref_uses_unspent_mana(qty: &QuantityRef) -> bool {
| QuantityRef::TrackedSetAggregate { .. }
| QuantityRef::ExiledFromHandThisResolution
| QuantityRef::PreviousEffectAmount { .. }
| QuantityRef::PreviousEffectCount
| QuantityRef::LifeLostThisTurn { .. }
| QuantityRef::PartySize { .. }
| QuantityRef::Speed { .. }
Expand Down Expand Up @@ -1301,6 +1302,7 @@ fn quantity_ref_uses_object_count(qty: &QuantityRef) -> bool {
| QuantityRef::TrackedSetAggregate { .. }
| QuantityRef::ExiledFromHandThisResolution
| QuantityRef::PreviousEffectAmount { .. }
| QuantityRef::PreviousEffectCount
| QuantityRef::LifeLostThisTurn { .. }
| QuantityRef::Speed { .. }
| QuantityRef::EventContextAmount
Expand Down Expand Up @@ -1596,6 +1598,7 @@ fn quantity_ref_characteristic_reads(qty: &QuantityRef, depth: u32) -> Character
| QuantityRef::TrackedSetSize
| QuantityRef::ExiledFromHandThisResolution
| QuantityRef::PreviousEffectAmount { .. }
| QuantityRef::PreviousEffectCount
| QuantityRef::LifeLostThisTurn { .. }
| QuantityRef::UnspentMana { .. }
| QuantityRef::Speed { .. }
Expand Down Expand Up @@ -1860,6 +1863,7 @@ fn entered_object_perturbs_quantity_ref(
| QuantityRef::TrackedSetAggregate { .. }
| QuantityRef::ExiledFromHandThisResolution
| QuantityRef::PreviousEffectAmount { .. }
| QuantityRef::PreviousEffectCount
| QuantityRef::LifeLostThisTurn { .. }
| QuantityRef::Speed { .. }
| QuantityRef::EventContextAmount
Expand Down Expand Up @@ -3990,6 +3994,9 @@ fn resolve_ref(
// (Contest of Claws). 0 when the preceding effect dealt no excess.
DamageChannel::Excess => state.last_effect_excess_amount.unwrap_or(0),
},
// Read the preceding continuation-local effect count directly.
// An unavailable count resolves to zero.
QuantityRef::PreviousEffectCount => state.last_effect_count.unwrap_or(0),
// CR 608.2c: "for each [thing] this way" — read the most recent tracked set size.
QuantityRef::TrackedSetSize => state
.tracked_object_sets
Expand Down
2 changes: 2 additions & 0 deletions crates/engine/src/game/triggers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10408,6 +10408,7 @@ fn quantity_ref_binding_diverges(qty: &QuantityRef) -> bool {
| QuantityRef::TrackedSetAggregate { .. }
| QuantityRef::ExiledFromHandThisResolution
| QuantityRef::PreviousEffectAmount { .. }
| QuantityRef::PreviousEffectCount
| QuantityRef::TimesCostPaidThisResolution
// CR 608.2c: the secret-number ledger is populated BY the
// resolution that ran the choice (Wheel of Misfortune, Menacing Ogre) and
Expand Down Expand Up @@ -13847,6 +13848,7 @@ fn quantity_ref_refs_cost_paid_object(qty: &QuantityRef) -> bool {
| QuantityRef::TrackedSetAggregate { .. }
| QuantityRef::ExiledFromHandThisResolution
| QuantityRef::PreviousEffectAmount { .. }
| QuantityRef::PreviousEffectCount
| QuantityRef::LifeLostThisTurn { .. }
| QuantityRef::PartySize { .. }
| QuantityRef::UnspentMana { .. }
Expand Down
Loading
Loading