-
Notifications
You must be signed in to change notification settings - Fork 824
Implement rooms (Bottomless Pool // Locker Room) #13786
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
base: master
Are you sure you want to change the base?
Conversation
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 style looks good, but it can be fully reviewed after unit tests added to make sure it's support all rule parts (the most important part -- copy and zone changing logic, also name searching/compare).
|
||
boolean unlockLeftHalf(Game game, Ability source); | ||
|
||
boolean unlockRightHalf(Game game, Ability source); |
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.
this.leftHalfUnlocked = true; | ||
|
||
// Fire generic door unlock event | ||
game.fireEvent(new GameEvent(GameEvent.EventType.UNLOCK_DOOR, getId(), source, source.getControllerId())); |
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.
"Unlock" naming for replacement and "unlocked" naming for passed events.
@@ -378,7 +388,11 @@ private static boolean maybeRemoveFromSourceZone(ZoneChangeInfo info, Game game, | |||
Permanent permanent; | |||
if (card instanceof MeldCard) { |
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.
Meld cards are badly tested by unit tests, so it's better to write room related tests for blinks, hand/stack/battlefield copy, etc.
* @author oscscull | ||
* Checks if a Permanent's left half is LOCKED (i.e., NOT unlocked). | ||
*/ | ||
public enum RoomLeftHalfLockedCondition implements Condition { |
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's good to use card hint to show rooms status in popup hints, e.g. "green icon left door unlocked", "red icon right door locked", etc
// Add abilities to remove locked door abilities - keep triggers or they won't trigger | ||
if (leftAbility != null && !(leftAbility instanceof UnlockThisDoorTriggeredAbility)) { | ||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( | ||
new LoseAbilitySourceEffect(leftAbility, Duration.WhileOnBattlefield), |
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.
Well, that's smells bad. Why you need to use such workaround with lose abilities effects? Use static trigger with conditional instead.
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.
mostly was trying to follow the word of
"709.5. Some split cards are permanent cards with a single shared type line. A shared type line on such an object represents two static abilities that function on the battlefield. These are “As long as this permanent doesn’t have the ‘left half unlocked’ designation, it doesn’t have the name, mana cost, or rules text of this object’s left half” and “As long as this permanent doesn’t have the ‘right half unlocked’ designation, it doesn’t have the name, mana cost, or rules text of this object’s right half.” These abilities, as well as which half of that permanent a characteristic is in, are part of that object’s copiable values."
So, as my understanding of the above, the room loses the ability when it's not unlocked. That approach is probably simpler though.
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.
Sadly it doesn't work cleanly (in the way I did it) because if the ability is lost, and the ability triggers on the unlock, the code that does the unlocking (including the event dispatch) happens in the wrong order. (The unlock happens, the event is fired, then the event checks for triggers, then the permanent gets the triggered ability back and misses the event)
@@ -50,7 +50,7 @@ public PermanentCard(Card card, UUID controllerId, Game game) { | |||
goodForBattlefield = false; | |||
} else if (card instanceof SplitCard) { | |||
// fused spells allowed (it uses main card) | |||
if (card.getSpellAbility() != null && !card.getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)) { | |||
if (card.getSpellAbility() != null && !card.getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED) && !(card instanceof RoomCard)) { |
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.
Edge case for room names which I do not believe is handled by the current hacky workaround for name:
|
Opalescence - (Gatherer) (Scryfall) (EDHREC)
Diviner's Wand - (Gatherer) (Scryfall) (EDHREC)
Pithing Needle - (Gatherer) (Scryfall) (EDHREC)
|
(Also speaking of Opalescence - make sure that the mana value of the room reflects the mana value of the unlocked sides; a non-cast Room should have zero mana value and die with Opalesence in play, a half-unlocked room should have the mana value of that unlocked side, and a fully unlocked room should have the total mana value.) |
Also check other room cards — some of it can contain unique logic and can require additional changes to support it. |
I will check these specifically. I have done a lot of changes to the code with opalescence + bile blight for local testing so that works for sure. Also testing mirage mirror and similar copy effects have a lot of edge cases. I asked the judge reddit for what happens when a room loses all its abilities + opalescence + muraganda petroglyphs but, got no definite answer. |
Thanks to all for the extensive reviews. Apologies, I've got limited time to work on this so I expect I will proceed in bursts when I get a chance. I'll address all of these and add unit tests this week if possible. |
this is a good point, I'll probably pull in several more to this PR. |
@@ -433,6 +434,15 @@ public boolean hasObjectTargetNameOrAlias(MageObject object, String nameOrAlias) | |||
return true; | |||
} | |||
|
|||
if (object instanceof RoomCard && object.getName().contains(" // ")) { |
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.
fixed
checkPlayableAbility("one land", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Bottomless Pool", true); | ||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bottomless Pool"); | ||
addTarget(playerA, "Grizzly Bears"); | ||
execute(); |
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'll follow this template - I added some tests already.
There are a lot of cases that might have issues so i'll be testing
Flicker - done
copy on stack
clone (etb)
copy (on battlefield)
a permanent that copies one room, then later copies a different room (mirage mirror)
then name related
on the stack
on the battlefield
in the graveyard (is there such an effect? I'll have to check)
before this can come out of drafts. might be more.
…over it with tests before i make this change
…ing something here?)
@@ -56,8 +56,6 @@ public void test_NamesEquals() { | |||
Assert.assertTrue(CardUtil.haveSameNames(splitCard1, "Armed // Dangerous", currentGame)); | |||
Assert.assertTrue(CardUtil.haveSameNames(splitCard1, splitCard1)); | |||
Assert.assertFalse(CardUtil.haveSameNames(splitCard1, "Other", currentGame)); | |||
Assert.assertFalse(CardUtil.haveSameNames(splitCard1, "Other // Dangerous", currentGame)); | |||
Assert.assertFalse(CardUtil.haveSameNames(splitCard1, "Armed // Other", currentGame)); | |||
Assert.assertFalse(CardUtil.haveSameNames(splitCard1, splitCard2)); |
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.
NOTE: If this test is relevant to an actual case, I'll have to adjust my approach. I couldn't think of a scenario where it comes up. Please check and confirm!
Specifically tested this |
Had a go at building room card functionality. There were some difficult parts, though the name issue wasn't really that bad (it seems the existing work around for split cards is basically fine).
It seems to work.
Part of #12534