-
Notifications
You must be signed in to change notification settings - Fork 745
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[PIP] Implement Codsworth, Handy Helper, improved attachment to permanent logic #12098
base: master
Are you sure you want to change the base?
[PIP] Implement Codsworth, Handy Helper, improved attachment to permanent logic #12098
Conversation
[[Codsworth, Handy Helper]] |
Codsworth, Handy Helper - (Gatherer) (Scryfall) (EDHREC)
|
Closes #12108 |
I feel like the attachment actions are not setup the best way. That being said, both cards here should be fine, so I'm not against merging as is, but could you please add a couple tests to make a future rework a little safer? Unit tests are really a great way to ensure current effort will not be undone by mistake in the future. |
I wrote some tests and hit a roadblock with one, in which moving an "Enchant land" aura to a creature would cause it to be moved to the graveyard, as opposed to not moving at all. Looking into this, it seems to be because mage/Mage/src/main/java/mage/game/GameImpl.java Lines 2493 to 2559 in fd0da67
Pushing tests now, including failing test (testIllegalAttachmentDenied) |
Fixed the problem of |
&& attachmentPermanent != null | ||
&& attachmentPermanent.getSpellAbility() != null | ||
&& !attachmentPermanent.getSpellAbility().getTargets().isEmpty()) { | ||
canAttach = game.getPermanent(attachment.getId()).getSpellAbility().getTargets().get(0).getFilter().match(this, game); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably use the 4 argument match(..)
Or else stuff like "Enchant creature you control" won't work properly.
Could you add a test on Codsworth trying to attach [[Captured by the Consulate]] to one of your creature (it shouldn't move)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Edit: Uhm you might not have easy access right now to the 4 argument match as it is only defined for FilterPermanent
, FilterCard
, FilterPlayer
, etc...
Should Filter
be changed to have 4 argument match defined? not sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a test on Codsworth trying to attach [[Captured by the Consulate]] to one of your creature (it shouldn't move)
Having written this test now, I can confirm it is currently failing. I'm not sure what you mean about how to account for this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the 4 argument match change you suggested to Permanent::cantBeAttachedBy
and can confirm that the previously failing test now passes. However, adding the checks for Player / Card to Permanent would be redundant as if we are calling the Permanent's cantBeAttachedBy method it's because we're trying to attach to a permanent specifically. The issue being that Players and Cards (and I suppose any other object, auras don't discriminate) don't have a cantBeAttachedBy
equivalent. I've written two tests for the cases of trying to use Codsworth to move auras that enchant players / cards to permanents which of course currently has the auras move illegally, and then sends them to the graveyard during state based actions. Am I missing something or does this need to be fixed via adding cantBeAttachedBy
equivalents to these objects (Player and Card)?
I suppose there could be a check in Permanent::cantBeAttachedBy for if the aura’s filter is an instance of FilterPlayer and immediately return true if so. I imagine the same applies to a FilterCard, unless a permanent is somehow included as a “card” in such a case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would make sense to have cantBeAttached
for Cards and Players, that for equipment/fortification always return true (as you can only attach an equipement to creatures and a fortification to a land), and for auras, checks that the target is of the proper kind, and checks its prerequisite.
Side note: are Curses properly falling off right now when they are named by Runed Halo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side note: are Curses properly falling off right now when they are named by Runed Halo?
Yes they are, but will add a test for that to this PR for future-proofing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, thanks for testing.
Those Attachment related methods sure do a lot in a various different places of the codebase.
Filter filter = attachmentPermanent.getSpellAbility().getTargets().get(0).getFilter(); | ||
if (filter instanceof FilterPermanent) { | ||
canAttach = ((FilterPermanent) filter).match(this, attachmentPermanent.getControllerId(), source, game); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would there be a downside to add
else {
canAttach = false;
}
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No; in fact, doing so causes the tests with Spellweaver Volute (enchant card in graveyard) and Psychic Possession (enchant opponent) to now pass.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I was expecting that, since they respectively have a FilterCard
and a FilterPlayer
for target.
The attach to permanent action should now work properly.
I guess if we ever have an attach/reattach not specific to permanents, there would need to be cantBeAttachedBy
in Card
/Player
that would look for their own Filter
.
If there is ever an Aura able to enchant both Permanent
and Player
, I guess the engine will burst into flames.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks good!
} | ||
|
||
if (creature.cantBeAttachedBy(attachment, source, game, true)) { | ||
game.informPlayers(attachment.getLogName() + " was not attached to " + creature.getLogName() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can add CardUtil.getSourceLogName(game, source)
at the end of most log.
Adds info for the source (Codsworth), and when you hover over it, it show the card image, which is nice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in 30d14e0
return game.getContinuousEffects().preventedByRuleModification(new StayAttachedEvent(this.getId(), attachment.getId(), source), null, game, silentMode); | ||
|
||
boolean canAttach = true; | ||
Permanent attachmentPermanent = game.getPermanent(attachment.getId()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why you load attachment to attachmentPermanent? It’s same object already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code brevity; it's more readable in the code to use a variable called attachmentPermanent
and use that than it is to write game.getPermanent(attachment.getId())
each time
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, I’m talking about “MageObject attachment” from method’s params. It’s same object, so why not to use it? Perm = ((Permanent) attachment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'll do that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is OK - I tested with casting an aura, making the aura's target illegal, and then resolving the aura. The outcome was, as expected, the aura going to the graveyard. Will add a test for futureproofing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Current code with game.getPermanent checks validation for permanents only (e.g. aura on battlefield try to reattach). But it will ignore card (e.g. aura moves from hand to battlefield without cast/stack).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Sneaking" an aura onto the battlefield with Eureka gives no opportunity for a permanent to become an illegal target before the user selects the target for the aura to attach to. In the case that there are no legal targets, the aura goes to the graveyard as it is unattached. Is that what you mean or did you have another interaction in mind?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See code screens above. Example with Unfinished Business:
Return target creature card from your graveyard to the battlefield, then return up to two target Aura and/or Equipment cards from your graveyard to the battlefield attached to that creature. (If the Auras can’t enchant that creature, they remain in your graveyard.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, of course. I have tested and can confirm that the interaction works as expected (the aura does not leave the graveyard). Will add a test for that case to this PR
Edit: Actually, there's a broken interaction with Unfinished Business. Looking into
Looks like there are many bug reports with attach problems, maybe something can be closed by that PR |
I believe that #11328 is fixed by this PR Halvar has issues fixed here |
Seems like Travis is ignoring this PR? |
Not ready to merge - despite not shown on GitHub there is a failing test and a couple more tests I plan to write |
No description provided.