Skip to content

fix(parser): Runadi, Behemoth Caller ETB counters and haste threshold - #6735

Merged
matthewevans merged 4 commits into
phase-rs:mainfrom
nghetien:fix/issue-6492-a1-runadi-behemoth-caller
Jul 29, 2026
Merged

fix(parser): Runadi, Behemoth Caller ETB counters and haste threshold#6735
matthewevans merged 4 commits into
phase-rs:mainfrom
nghetien:fix/issue-6492-a1-runadi-behemoth-caller

Conversation

@nghetien

@nghetien nghetien commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Runadi's first ability ("Whenever you cast a creature spell with mana value 5 or greater, that creature enters with X additional +1/+1 counters on it, where X is its mana value minus 4.") failed to parse the composite "where X is its mana value minus 4" quantity clause — the atomic-only parse_quantity_ref call couldn't express arithmetic, so the whole parse_whenever_you_cast_enters_with combinator bailed via ? and the ability fell through to the generic self-ETB fallback (parse_enters_with_counters), which wrongly scoped the effect to Runadi herself (valid_card: SelfRef) instead of the cast creature, and absorbed the mana-value condition text as a garbage literal counter type.
  • Fixed by delegating the trailing quantity clause to parse_enters_with_where_x_suffix (the existing shared authority for this grammar, already used by the sibling self-ETB path), which supports composite/offset expressions.
  • Runtime-side, ObjectScope::Recipient's resolution (object_for_scope/object_id_for_scope in game/quantity.rs) never consulted QuantityContext.entering (the object entering the battlefield in an ETB-scoped replacement), so "its mana value" would have resolved to the static replacement source (Runadi) rather than the entering creature. Added an entering fallback between the existing recipient/targets checks and the final source fallback — inert for every non-ETB caller (ctx.entering is only ever set by ETB-counter extraction), so existing CR 613.4c layer-recipient consumers (Blessing of the Nephilim, Civic Saber) are unaffected.
  • Separately (a second, independent bug the issue title also called out — "doesn't give creatures counters and haste"): the haste static's Oracle text ("Creatures you control with three or more +1/+1 counters on them have haste.") parsed to Counters { counters: OfType(Generic("or more +1/+1")), ... } — the counter-count parser consumed "three" and a single trailing space but never stripped the redundant "or more"/"or greater" qualifier, so it leaked into the counter-type slice. No creature could ever match the filter, so haste never applied even once counters existed. Fixed by stripping the qualifier after the count, mirroring the existing CMC "N or greater" handling.

Files changed

  • crates/engine/src/parser/oracle_replacement.rs — delegate parse_whenever_you_cast_enters_with's "where X is" clause to the shared composite-quantity parser; added parses_runadi_behemoth_caller_replacement and whenever_you_cast_enters_with_garbage_quantity_fails_closed tests.
  • crates/engine/src/game/quantity.rs — added ctx.entering fallback to ObjectScope::Recipient resolution in object_for_scope and object_id_for_scope.
  • crates/engine/src/types/ability.rs — updated ObjectScope::Recipient doc comment to describe the completed resolution chain.
  • crates/engine/src/parser/oracle_target.rs — strip redundant "or more "/"or greater " after a counter count in parse_counter_spec_after_lead; added parse_counter_suffix_three_or_more_plus1plus1 and parse_counter_suffix_two_or_greater_stun regression tests.
  • crates/engine/tests/integration/runadi_behemoth_caller_etb_counters.rs (new) — 3 runtime tests: MV8 creature enters with 4 counters and gains haste; MV5 creature enters with exactly 1 counter, no haste; MV4 creature enters with 0 counters (filter correctly excludes it), no haste.
  • crates/engine/tests/integration/main.rs — registered the new test module.

Track: Developer

Model: claude-sonnet-5
Tier: Frontier
Thinking: high

Implementation method (required): Method: not-applicable — root-caused and fixed directly after an initial /engine-implementer planning+review-plan round (which surfaced two real gaps that were incorporated); the full plan→review-plan→implement→review-impl pipeline could not be completed end-to-end within this session's time budget after an earlier interruption, so this is a direct, carefully-verified hand fix rather than a completed pipeline run.

CR references: CR 614.1c (enters-with replacement effects), CR 202.3 (mana value), CR 107.1 + CR 604.3 (arithmetic quantity expressions), CR 613.4c (recipient-scoped continuous effects / layer 7c), CR 122.1 (counter-count filter comparators)

Verification

  • cargo fmt --all -- --check — clean
  • cargo clippy --workspace --exclude phase-tauri --all-targets --features engine/proptest -- -D warnings — clean (fixed one unnecessary_lazy_evaluations lint along the way)
  • Targeted unit tests (cargo test -p engine --lib): parses_runadi_behemoth_caller_replacement, whenever_you_cast_enters_with_garbage_quantity_fails_closed, parses_wildgrowth_archaic_replacement (sibling, no regression), parses_fixed_count_variant (sibling, no regression), plain_whenever_you_cast_is_not_replacement (no regression), parse_counter_suffix_three_or_more_plus1plus1, parse_counter_suffix_two_or_greater_stun, all existing parse_counter_suffix_* tests, resolve_object_mana_value_* (no regression) — all pass.
  • Targeted runtime integration tests (cargo test -p engine --test integration runadi): all 3 new tests pass (MV8→4 counters+haste, MV5→1 counter/no haste, MV4→0 counters/no haste).
  • Full cargo nextest run --profile ci --workspace --exclude phase-tauri --exclude mtgish-import --features engine/proptest — started but did not finish confirming within this session due to a mid-run interruption; not run to completion locally. Every directly-relevant test (all touched functions' existing + new tests) was run individually and passed; the shared ObjectScope::Recipient resolver change is scoped narrowly enough (only reachable when ctx.entering is Some, set at exactly two call sites, both ETB-counter extraction) that a workspace-wide regression is considered unlikely, but this is not proven by a full suite run.

Gate A: not generated this round (no PR/CI run yet).

Anchored on:

  • crates/engine/src/parser/oracle_replacement.rs:4741 (parse_whenever_you_cast_enters_with) — root cause of the counter-scoping bug
  • crates/engine/src/game/quantity.rs:4687 (object_for_scope's Recipient arm) — root cause of the runtime scope-resolution gap
  • crates/engine/src/parser/oracle_target.rs:5527 (parse_counter_spec_after_lead's count parser) — root cause of the haste-filter garbage counter type

Final review-impl: not run this round (see Method note above).

Claimed parse impact: Fixes Runadi, Behemoth Caller's first ability (ETB counters) and second ability (haste threshold) end-to-end; the composite quantity-clause fix and the Recipient-scope fix generalize to the whole "Wildgrowth Archaic cousin" card family (Boreal Outrider, Torgal, and any future card using this shape with an arithmetic mana-value/power/toughness quantity); the "or more"/"or greater" counter-count fix generalizes to any card using "with N or more/or greater counter(s)" in a filter.

Scope Expansion: None.

Validation Failures: Full-workspace cargo nextest was not completed this session (see Verification above) — flagging honestly rather than claiming false completeness.

CI Failures: None observed in what was run.

Closes #6492

Summary by CodeRabbit

  • New Features
    • Enhanced ETB replacement resolution so quantity reads use the correct “entering” permanent.
    • Updated “Whenever you cast … enters with … counters …” handling to follow the proper trigger-based flow for the cast spell.
  • Bug Fixes
    • Counter thresholds now correctly accept “or more” / “or greater.”
    • Trigger-based counter replacements now reliably bind to the specific triggering spell (including delayed resolution and when Runadi leaves play) and fail safely for unrecognized counter text.
  • Documentation
    • Clarified recipient-relative targeting and effect/quantity resolution guidance.
  • Tests
    • Added/updated integration coverage for Runadi, Behemoth Caller (counters, haste condition, ordering, and rule-interaction cases).

Runadi's first ability failed to parse its composite "where X is its
mana value minus 4" quantity clause, misrouting the whole ability to
the generic self-ETB fallback and scoping the counter grant to Runadi
herself instead of the cast creature. Delegate to the shared
where-X-is suffix parser (already used by the sibling self-ETB path)
so composite/offset quantities resolve here too, and thread the
entering object through the Recipient scope resolver so "its mana
value" reads the creature actually entering, not the static source.

Separately, the haste static's "with three or more +1/+1 counters"
filter left "or more" stuck onto the counter-type text (a garbage
Generic("or more +1/+1") counter type), so no creature ever matched
and haste never applied. Strip the redundant or-more/or-greater
qualifier after the count, mirroring the existing mana-value handling.
@nghetien
nghetien requested a review from matthewevans as a code owner July 28, 2026 18:43
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 81f714f6-b706-4c19-8e86-f68e208355aa

📥 Commits

Reviewing files that changed from the base of the PR and between 3ddbe75 and 48ebcdb.

📒 Files selected for processing (2)
  • crates/engine/src/parser/oracle.rs
  • crates/engine/tests/integration/main.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/engine/tests/integration/main.rs
  • crates/engine/src/parser/oracle.rs

📝 Walkthrough

Walkthrough

The parser now represents cast-based “enters with counters” abilities as one-shot triggers, supports composite “where X is” quantities and counter-threshold qualifiers, and resolves recipient quantities against entering objects during ETB replacements. Runadi integration tests cover counters, haste, source removal, and spell-specific replacement binding.

Changes

ETB quantity and parser behavior

Layer / File(s) Summary
Cast-trigger parsing and replacement binding
crates/engine/src/parser/oracle_replacement.rs, crates/engine/src/parser/oracle.rs, crates/engine/src/game/effects/add_target_replacement.rs, crates/engine/src/types/identifiers.rs
Cast-based “enters with counters” text now produces a floating one-shot SpellCast trigger, with its replacement bound to the triggering spell and shared parsing for composite quantity expressions.
Entering-object recipient resolution
crates/engine/src/game/quantity.rs, crates/engine/src/types/ability.rs
Recipient-scoped object and identity lookups prefer the ETB entering object, with corresponding resolution documentation updates.
Counter thresholds and Runadi validation
crates/engine/src/parser/oracle_target.rs, crates/engine/tests/integration/main.rs, crates/engine/tests/integration/runadi_behemoth_caller_etb_counters.rs
Counter parsing consumes “or more” and “or greater” qualifiers; Runadi tests cover mana-value-based counters, haste thresholds, source removal, and separate replacement resolution for two spells.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SpellCast
  participant OracleParser
  participant Trigger
  participant AddTargetReplacement
  participant EnteringCreature
  SpellCast->>OracleParser: parse enters-with-counters text
  OracleParser->>Trigger: create SpellCast trigger
  Trigger->>AddTargetReplacement: install replacement bound to spell
  AddTargetReplacement->>EnteringCreature: apply counters on entry
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is clear and matches the main Runadi ETB counter and haste-threshold fix, even though the changes also include runtime resolution updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown

Parse changes introduced by this PR · 8 card(s), 11 signature(s) (baseline: main eeb8c498400f)

🟢 Added (3 signatures)

  • 2 cards · ➕ trigger/SpellCast · added: SpellCast (active in=battlefield, valid target=controller, watches=you control creature)
    • Affected (first 3): Communal Brewing, Wildgrowth Archaic
  • 1 card · ➕ trigger/SpellCast · added: SpellCast (active in=battlefield, valid target=controller, watches=mv 5+ you control creature)
    • Affected (first 3): Runadi, Behemoth Caller
  • 1 card · ➕ trigger/Whenever a creature you control with one or more counters on it dies · added: Whenever a creature you control with one or more counters on it dies (active in=battlefield)
    • Affected (first 3): Shadow Urchin

🔴 Removed (3 signatures)

  • 2 cards · ➖ replacement/ChangeZone · removed: ChangeZone (scope=you control creature, to zone=battlefield)
    • Affected (first 3): Communal Brewing, Wildgrowth Archaic
  • 1 card · ➖ trigger/ChangesZone · removed: ChangesZone (active in=battlefield, from=battlefield, to=graveyard, watches=1+ or more counters you control creature)
    • Affected (first 3): Shadow Urchin
  • 1 card · ➖ replacement/Moved · removed: Moved (scope=self, to zone=battlefield)
    • Affected (first 3): Runadi, Behemoth Caller

🟡 Modified fields (5 signatures)

  • 1 card · 🔄 trigger/ChangesZone · changed field watches: nontoken 1+ or more oil counters you control creaturenontoken 1+ oil counters you control creature
    • Affected (first 3): Gyox, Brutal Carnivora
  • 1 card · 🔄 static/Continuous · changed field affects: 1+ or more loyalty counters planeswalker1+ loyalty counters planeswalker
    • Affected (first 3): Spark Rupture
  • 1 card · 🔄 static/Continuous · changed field affects: 3+ or more +1/+1 counters you control creature3+ P1P1 counters you control creature
    • Affected (first 3): Runadi, Behemoth Caller
  • 1 card · 🔄 static/Continuous · changed field conditional: 3+ or more level counters in battlefield you control creature is present3+ level counters in battlefield you control creature is present
    • Affected (first 3): Champion's Drake
  • 1 card · 🔄 ability/Mana · changed field conditional: instead if (# of 12+ or more charge counters in battlefield you control Planet ≥ 1)instead if (# of 12+ charge counters in battlefield you control Planet ≥ 1)
    • Affected (first 3): Brood Astronomer

1 card(s) had Oracle-text changes (errata/reprint) — excluded as non-parser.

@matthewevans matthewevans self-assigned this Jul 28, 2026

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested

Reviewed at current head a475003e30bf127aba9482c4b06553ff43122fc4.

[BLOCKING] Runadi’s Whenever you cast … ability is modeled as a static, object-hosted replacement, so it stops working if Runadi leaves before the cast creature resolves. oracle_replacement.rs:705-709 routes the whole sentence through parse_whenever_you_cast_enters_with, and :4728-4736 / :4828-4842 lower it to ReplacementDefinition. The replacement scan in game/replacement.rs:6249-6281 admits this source only from battlefield/command, whereas triggered abilities follow the independent trigger/stack path in functioning_abilities.rs:439-449.

The local official CR source confirms the distinction: CR 603.1 defines Whenever as a triggered ability and CR 603.3 puts it on the stack. CR 614.1c/614.12 covers the later enter-with replacement, not erasing the preceding trigger. Thus, removing Runadi after the cast but before the spell resolves loses the effect entirely; the implementation also never uses the stack for this ability. The new integration test resolves while Runadi remains on the battlefield, so it cannot expose that case.

Please model the Whenever you cast … portion as a TriggerDefinition, whose resolution creates a floating, entrant-bound replacement for the qualifying spell’s battlefield entry (or retain honest unsupported coverage until that exists). Add a regression that removes Runadi after the trigger is created and proves the qualified spell still enters with the correct counters; preserve the no-qualifying-spell behavior as well. Do not address this by widening the object-hosted replacement zones.

@matthewevans matthewevans removed their assignment Jul 28, 2026
@matthewevans matthewevans self-assigned this Jul 29, 2026

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested — the trigger is now correctly stack-based, but its one-shot replacement is still not bound to the spell that triggered it.

🔴 Blocker

[HIGH] The floating replacement can be consumed by a different qualifying creature before the triggering spell resolves. Evidence: crates/engine/src/parser/oracle_replacement.rs:4911-4916 installs AddTargetReplacement with TargetFilter::None; crates/engine/src/game/effects/add_target_replacement.rs:231-242 consequently pushes that payload into the global pending-replacement registry. The parser comment at oracle_replacement.rs:4890-4895 assumes no event can interleave after the trigger resolves, but that is false: after the spell-cast trigger resolves, CR 117.3b gives the active player priority. They can cast another qualifying flash creature, whose battlefield entry is then the first matching zone-change event and consumes the one-shot replacement.

The replacement must be bound to the triggering SpellCast object through the event-context TriggeringSource / host semantics, rather than a global TargetFilter::None scan. Please add a runtime regression that casts two qualifying entrants with the second entering during that priority window, and proves the counters apply only to the original triggering spell's entrant.

The parse-diff sticky (<!-- coverage-parse-diff -->, comment 5108471570) was generated at 2026-07-28T18:58:35Z and predates this head (6f7275e5287ac73aab64875fae7875fd796f9d08, committed 2026-07-28T19:38:21Z). Regenerate/reconcile current-head parse-diff evidence after CI; this is evidence freshness, not a separate correctness finding.

Recommendation: request changes — preserve the trigger design, bind the replacement to its triggering spell, and cover the interleaving case.

@matthewevans matthewevans removed their assignment Jul 29, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/engine/src/parser/oracle_replacement.rs`:
- Around line 4875-4927: Scope the floating replacement created by
parse_whenever_you_cast_enters_with_trigger to the specific spell instance that
caused the SpellCast trigger, rather than matching any qualifying battlefield
entry. Preserve the existing pending_damage_replacements installation and
consume_on_apply behavior, but ensure find_applicable_replacements can reject
entries from other spells before consuming the replacement.

In `@crates/engine/tests/integration/runadi_behemoth_caller_etb_counters.rs`:
- Around line 177-182: Replace the direct `GameObject.zone` mutation for
`runadi` in the scenario setup with the existing `scenario`/`runner` zone-change
API that emits the replacement-aware `ProposedEvent::ZoneChange` pipeline.
Assert that Runadi is in the graveyard before calling `commit.resolve()`, while
preserving the existing stack and trigger setup.
- Around line 128-139: The MV4 negative test lacks a positive reach guard and
can pass if Runadi’s trigger was never registered. Update
runadi_grants_no_counters_below_mv5_threshold and its setup path to assert the
relevant ability parses successfully without Effect::Unimplemented and the
creature uses the normal runtime pipeline before retaining the existing (0,
false) filter assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c3ce4b2e-2233-41b9-8771-5edd3138611c

📥 Commits

Reviewing files that changed from the base of the PR and between a475003 and 6f7275e.

📒 Files selected for processing (3)
  • crates/engine/src/parser/oracle.rs
  • crates/engine/src/parser/oracle_replacement.rs
  • crates/engine/tests/integration/runadi_behemoth_caller_etb_counters.rs

Comment thread crates/engine/src/parser/oracle_replacement.rs
The one-shot floating replacement Runadi's SpellCast trigger installs
was scoped only by type/mana-value filter, so a different qualifying
creature entering the battlefield during the priority window between
the trigger resolving and the originally-cast spell resolving could
consume it first, leaving the intended entrant uncountered.

Bind the install to the specific spell that caused the trigger: the
parser embeds a TRIGGERING_SPELL_PLACEHOLDER sentinel inside the
replacement's valid_card (AND-combined with the existing filter), and
Effect::AddTargetReplacement's resolve function concretizes it to the
real triggering spell's id from the current trigger event at install
time (or to a match-nothing id if none is extractable). Using a
sentinel object id instead of a new ReplacementDefinition field avoids
rippling a struct change through every exhaustive construction site,
including the dormant mtgish-import crate.

Also address review nits: the "Runadi leaves before the spell
resolves" regression now drives the departure through the production
zone-change pipeline instead of poking the object's zone field
directly, and the negative mana-value test asserts the trigger
actually registered before checking the zero-counter outcome. Added a
new regression that casts two qualifying creatures back to back,
proving each entrant gets only its own counters.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
crates/engine/src/game/effects/add_target_replacement.rs (1)

76-119: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Make the placeholder walk exhaustive. TargetFilter is a closed enum, but both helpers fall back to _ for unknown variants. That lets a future composite TargetFilter variant silently skip placeholder binding and leave the trigger source unbound. Match every current leaf explicitly so the compiler forces this code to be updated when TargetFilter grows.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/engine/src/game/effects/add_target_replacement.rs` around lines 76 -
119, Make target_filter_contains_placeholder and
concretize_triggering_spell_placeholder exhaustively match every current
TargetFilter variant instead of using wildcard arms. Explicitly handle each leaf
variant with the existing non-placeholder behavior, while preserving recursive
handling for And, Or, and Not, so adding a new variant causes a compiler error
until these helpers are updated.

Sources: Coding guidelines, Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/engine/src/game/effects/add_target_replacement.rs`:
- Around line 76-119: Make target_filter_contains_placeholder and
concretize_triggering_spell_placeholder exhaustively match every current
TargetFilter variant instead of using wildcard arms. Explicitly handle each leaf
variant with the existing non-placeholder behavior, while preserving recursive
handling for And, Or, and Not, so adding a new variant causes a compiler error
until these helpers are updated.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f2a2813d-7652-434d-aeac-05349af0ddd1

📥 Commits

Reviewing files that changed from the base of the PR and between 6f7275e and 3ddbe75.

📒 Files selected for processing (4)
  • crates/engine/src/game/effects/add_target_replacement.rs
  • crates/engine/src/parser/oracle_replacement.rs
  • crates/engine/src/types/identifiers.rs
  • crates/engine/tests/integration/runadi_behemoth_caller_etb_counters.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/engine/src/parser/oracle_replacement.rs

@matthewevans matthewevans self-assigned this Jul 29, 2026

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved at current head 48ebcdb: stack-trigger binding, spell-specific floating replacement, current parse-diff, and discriminating runtime interleaving coverage verified.

@matthewevans matthewevans added the bug Bug fix label Jul 29, 2026
@matthewevans
matthewevans added this pull request to the merge queue Jul 29, 2026
@matthewevans matthewevans removed their assignment Jul 29, 2026
Merged via the queue into phase-rs:main with commit 694200e Jul 29, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Runadi, Behemoth Caller — Runadi doesn't give creatures counters and haste when casting mana value 5 or greater.

2 participants