Skip to content

fix(engine): retain look-result loop members - #7285

Merged
matthewevans merged 8 commits into
mainfrom
ship/fix-engine-retain-look-result-loop-members
Aug 12, 2026
Merged

fix(engine): retain look-result loop members#7285
matthewevans merged 8 commits into
mainfrom
ship/fix-engine-retain-look-result-loop-members

Conversation

@matthewevans

@matthewevans matthewevans commented Aug 12, 2026

Copy link
Copy Markdown
Member

Fixes #7151.

Retains the exact Dig result collection for the immediate member-driven loop, so Moonlight Bargain never substitutes unrelated battlefield permanents while resolving its per-card payment prompts.

Summary by CodeRabbit

  • Bug Fixes

    • Improved “for each” effects to preserve target selections across nested effects and correctly process member-driven repeats.
    • Ensured payment actions use the correct revealed cards and prompt separately for each applicable card.
    • Prevented unrelated battlefield objects from being included in card-selection and payment actions.
    • Restricted certain batch life-change effects to the appropriate spell context.
    • Improved matching by preserving candidate order, removing duplicates, and excluding invalid objects.
    • Prevented private card-selection details from appearing in payment prompts.
  • Tests

    • Added regression coverage for Moonlight Bargain, including card movement, life loss, and revealed-card selection.

@matthewevans
matthewevans enabled auto-merge August 12, 2026 04:40
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@matthewevans, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 8 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 66eb9156-c8d3-4468-a8b9-1250e2db758f

📥 Commits

Reviewing files that changed from the base of the PR and between d9a2229 and c0da507.

📒 Files selected for processing (4)
  • crates/engine/src/game/engine.rs
  • crates/engine/src/game/quantity.rs
  • crates/engine/src/types/ability.rs
  • crates/engine/tests/integration/main.rs

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: b986a76a-640d-450e-bb43-ffa0f7b95027

📥 Commits

Reviewing files that changed from the base of the PR and between 8deed8d and d9a2229.

📒 Files selected for processing (4)
  • crates/engine/src/game/effects/mod.rs
  • crates/engine/src/game/engine.rs
  • crates/engine/src/types/ability.rs
  • crates/engine/tests/integration/main.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/engine/tests/integration/main.rs
  • crates/engine/src/types/ability.rs
  • crates/engine/src/game/effects/mod.rs

📝 Walkthrough

Walkthrough

Changes

The engine now carries parent-produced iteration member IDs through child effects. Matching uses ordered candidate snapshots. Member-driven repeats handle per-member payment resolution and repeat state. Visibility projections redact private iteration IDs. Regression tests cover payment resolution and target preservation.

Iteration target flow

Layer / File(s) Summary
Candidate contracts and storage
crates/engine/src/types/ability.rs, crates/engine/src/game/quantity.rs
Abilities store optional parent iteration members. Object-count matching filters, deduplicates, and preserves supplied candidate order.
Iteration propagation and rebinding
crates/engine/src/game/effects/mod.rs, crates/engine/src/game/engine.rs
Member-driven iteration preserves carried collections, stamps immediate children, clears stale descendant context, defers per-member payment handling, and manages repeat state.
Resolution eligibility and interaction visibility
crates/engine/src/game/stack.rs, crates/engine/src/game/visibility.rs, crates/engine/tests/integration/issue_7151_moonlight_bargain.rs, crates/engine/tests/integration/main.rs
Batch life-change paths require default spell context. Viewer projections redact private iteration IDs. Tests validate payment iterations, resulting zones, life loss, and unrelated permanents.

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

Sequence Diagram(s)

sequenceDiagram
  participant Player
  participant Effects
  participant Quantity
  participant ViewerState
  Player->>Effects: resolve Moonlight Bargain payment iteration
  Effects->>Quantity: match targets within carried Dig IDs
  Quantity-->>Effects: return one revealed card target
  Effects->>ViewerState: redact private iteration IDs
  ViewerState-->>Player: present payment choice
  Player->>Effects: accept or decline card
  Effects-->>Player: move card to hand or graveyard
Loading

Possibly related PRs

Suggested labels: bug, test

Suggested reviewers: jacobwoodson, lgray

🚥 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 clearly summarizes the primary change: retaining members from look-result loops.
Linked Issues check ✅ Passed The changes address issue #7151 by preserving Dig result members during payment iterations and include a regression test for the reported behavior.
Out of Scope Changes check ✅ Passed The changes support the loop-member retention fix, including payment handling, candidate matching, visibility, serialization, and regression coverage.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ship/fix-engine-retain-look-result-loop-members

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/engine/src/game/effects/mod.rs (1)

11390-11450: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Stamp propagated targets for member-driven repeats.

When this branch propagates object targets to a sub-ability with repeat_for: ObjectCount and a ParentTarget reference, apply_parent_chain_context clears parent_target_iteration_members. The resolver then scans the battlefield instead of the propagated targets.

Call stamp_parent_target_iteration_members(&mut sub_with_targets) after apply_parent_chain_context.

🤖 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/mod.rs` around lines 11390 - 11450, The target
propagation branch should preserve member-driven repeat context when the
sub-ability uses repeat_for: ObjectCount with a ParentTarget reference. After
apply_parent_chain_context(&mut sub_with_targets, ...), call
stamp_parent_target_iteration_members(&mut sub_with_targets) before
resolve_ability_chain so resolution iterates the propagated targets rather than
rescanning the battlefield.
🤖 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/game/effects/mod.rs`:
- Around line 5895-5906: Update rebind_member_driven_parent_target so member
rebinding replaces only the relevant object target while preserving all
non-object targets, especially the selected TargetRef::Player. Keep the existing
complete-list replacement behavior for the carried look-result collection, but
include retained non-object targets so SearchLibrary::resolve_library_owner
continues reading the correct player.

In `@crates/engine/src/types/ability.rs`:
- Around line 20475-20479: Update filter_state_for_viewer so every
opponent-facing ResolvedAbility projection clears
PendingCast.ability.parent_target_iteration_members while preserving the field
for the owning viewer; add a regression test verifying the IDs are redacted from
opponent state.

---

Outside diff comments:
In `@crates/engine/src/game/effects/mod.rs`:
- Around line 11390-11450: The target propagation branch should preserve
member-driven repeat context when the sub-ability uses repeat_for: ObjectCount
with a ParentTarget reference. After apply_parent_chain_context(&mut
sub_with_targets, ...), call stamp_parent_target_iteration_members(&mut
sub_with_targets) before resolve_ability_chain so resolution iterates the
propagated targets rather than rescanning the battlefield.
🪄 Autofix

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: 05c6ad90-1d56-407c-bf2a-5d431dbcaf2b

📥 Commits

Reviewing files that changed from the base of the PR and between 58107f7 and 90fa916.

📒 Files selected for processing (6)
  • crates/engine/src/game/effects/mod.rs
  • crates/engine/src/game/quantity.rs
  • crates/engine/src/game/stack.rs
  • crates/engine/src/types/ability.rs
  • crates/engine/tests/integration/issue_7151_moonlight_bargain.rs
  • crates/engine/tests/integration/main.rs

Comment thread crates/engine/src/game/effects/mod.rs
Comment thread crates/engine/src/types/ability.rs
@matthewevans
matthewevans force-pushed the ship/fix-engine-retain-look-result-loop-members branch from 19d539a to dc30f4b Compare August 12, 2026 05:12

@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: 2

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

3094-3113: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a CR citation to stamp_parent_target_iteration_members.

This function implements a rules-relevant provenance rule (look-result membership ownership), but it carries no CR <number>: <description> annotation. Sibling functions in the same file cite CR 701.20e + CR 608.2c for the same concept (apply_parent_chain_context at Line 2468, rebind_member_driven_parent_target at Line 5895).

Add the same or an equivalent citation here for consistency and future auditability.

As per path instructions, "rules-touching code with no verified CR <number>: <description> annotation" is a finding for crates/engine/**.

🤖 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/mod.rs` around lines 3094 - 3113, Add a
verified rules citation comment to stamp_parent_target_iteration_members,
documenting the look-result membership ownership rule; use the same CR 701.20e +
CR 608.2c citation as apply_parent_chain_context and
rebind_member_driven_parent_target, or an equivalent accurate CR reference.

Source: 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.

Inline comments:
In `@crates/engine/src/game/effects/mod.rs`:
- Around line 9592-9600: Update resolve_effect’s deferred unless_pay path to
also detect member-driven abilities with no sub_ability and optional == false,
including iter_effective.unless_pay.is_some() in the chain re-entry condition.
Before re-entering, clear iter_ability.repeat_for so TrackedSetSize continues
using the existing outer repeat driver while the payment is applied per member.
Add a regression test covering this non-optional member-driven unless_pay case.

In `@crates/engine/src/game/visibility.rs`:
- Around line 28-35: Update redact_waiting_for_iteration_members to match every
WaitingFor variant explicitly instead of using a wildcard arm: retain redaction
for UnlessPayment and UnlessPaymentChooseCost, and list all current
non-redaction variants as explicit no-op arms so future ResolvedAbility-carrying
variants cannot bypass projection review.

---

Nitpick comments:
In `@crates/engine/src/game/effects/mod.rs`:
- Around line 3094-3113: Add a verified rules citation comment to
stamp_parent_target_iteration_members, documenting the look-result membership
ownership rule; use the same CR 701.20e + CR 608.2c citation as
apply_parent_chain_context and rebind_member_driven_parent_target, or an
equivalent accurate CR reference.
🪄 Autofix

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: eb109ebb-ec09-46a5-a03d-68cd342fa379

📥 Commits

Reviewing files that changed from the base of the PR and between 90fa916 and 8deed8d.

📒 Files selected for processing (3)
  • crates/engine/src/game/effects/mod.rs
  • crates/engine/src/game/visibility.rs
  • crates/engine/tests/integration/issue_7151_moonlight_bargain.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/engine/tests/integration/issue_7151_moonlight_bargain.rs

Comment thread crates/engine/src/game/effects/mod.rs
Comment thread crates/engine/src/game/visibility.rs
@matthewevans
matthewevans force-pushed the ship/fix-engine-retain-look-result-loop-members branch 2 times, most recently from ee1b29e to d4be186 Compare August 12, 2026 07:04
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

Generated for head c0da507b7bc3a2491b1539dc403862299c2c33ea.

Parse changes introduced by this PR

✓ No card-parse changes detected.

@matthewevans
matthewevans force-pushed the ship/fix-engine-retain-look-result-loop-members branch from d4be186 to 217be06 Compare August 12, 2026 07:31
@matthewevans
matthewevans added this pull request to the merge queue Aug 12, 2026
Merged via the queue into main with commit b29c730 Aug 12, 2026
15 checks passed
@matthewevans
matthewevans deleted the ship/fix-engine-retain-look-result-loop-members branch August 12, 2026 10:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Game unexpectedly deletes all permanents while a cost is shown

1 participant