Skip to main content

manabrew_engine/ability/effects/
bond_effect.rs

1//! Bond effect — partner/bond mechanic for pairing creatures.
2//!
3//! Ported from Java's `BondEffect.java`.
4//! Bond: Pair two creatures together (Soulbond).
5
6use forge_foundation::ZoneType;
7
8use super::EffectContext;
9use crate::ids::CardId;
10
11/// Struct form of this effect so it can participate in the
12/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
13/// `BondEffect` class extending `SpellAbilityEffect`.
14#[manabrew_engine_macros::spell_effect(BondEffect)]
15fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
16    let Some(source_id) = sa.source else { return };
17    let controller = sa.activating_player;
18
19    if ctx.game.card(source_id).zone != ZoneType::Battlefield {
20        return;
21    }
22
23    // Find an unpaired creature to bond with
24    let candidates: Vec<CardId> = ctx
25        .game
26        .cards
27        .iter()
28        .filter(|c| {
29            c.zone == ZoneType::Battlefield
30                && c.controller == controller
31                && c.id != source_id
32                && c.type_line
33                    .core_types
34                    .iter()
35                    .any(|ct| matches!(ct, forge_foundation::CoreType::Creature))
36                && c.paired_with.is_none()
37        })
38        .map(|c| c.id)
39        .collect();
40
41    if candidates.is_empty() {
42        return;
43    }
44
45    // Optional — player may decline
46    if sa.is_optional() {
47        ctx.agents[controller.index()].snapshot_state(ctx.game, ctx.mana_pools);
48        if !ctx.agents[controller.index()].confirm_action(
49            controller,
50            Some("Bond"),
51            "Pair with a creature?",
52            &[],
53            None,
54            None,
55        ) {
56            return;
57        }
58    }
59
60    ctx.agents[controller.index()].snapshot_state(ctx.game, ctx.mana_pools);
61    if let Some(partner) = ctx.agents[controller.index()].choose_single_card_for_zone_change(
62        ctx.game,
63        controller,
64        &candidates,
65        "Choose a creature to pair with",
66        false,
67    ) {
68        ctx.game.card_mut(source_id).set_paired_with(Some(partner));
69        ctx.game.card_mut(partner).set_paired_with(Some(source_id));
70    }
71}