3535 * that check entirely, or grants a shared budget of {@code n} extra colors (deck-wide DISTINCT
3636 * colors, not card count) to cards matching a {@code Type:} branch. Branches tokenize dot-then-plus
3737 * like {@code ValidCard$} restriction strings (type/supertype/subtype words, {@code Permanent}, or
38- * a stat filter like {@code powerGE4}).
38+ * a stat filter like {@code powerGE4}). A creature-type token also matches cards with Changeling,
39+ * which is every creature type per rule 702.73a (mirrors the same handling already established in
40+ * {@link forge.card.DeckHints}).
3941 */
4042public class DeckRuleColorIdentity extends DeckRule {
4143 private static final Pattern STAT_FILTER =
@@ -60,7 +62,7 @@ boolean matches(final CardRules card) {
6062 }
6163 }
6264 for (final String sub : typeSpec .getSubtypes ()) {
63- if (!candidate .hasSubtype (sub )) {
65+ if (!candidate .hasSubtype (sub ) && !( CardType . isACreatureType ( sub ) && hasChangeling ( card )) ) {
6466 return false ;
6567 }
6668 }
@@ -74,6 +76,17 @@ boolean matches(final CardRules card) {
7476 }
7577 return true ;
7678 }
79+
80+ /**
81+ * True if {@code card} has Changeling, making it every creature type - rule 702.73a: "This ability
82+ * works everywhere, even outside the game." Same {@code Type:} branch a normal creature-type card
83+ * would need to match, just sourced from the keyword instead of the printed subtypes. Mirrors
84+ * {@link forge.card.DeckHints}'s existing {@code CardType.isACreatureType(p)} + {@code hasKeyword("Changeling")}
85+ * handling for the same problem.
86+ */
87+ private static boolean hasChangeling (final CardRules card ) {
88+ return CardRulesPredicates .hasKeyword ("Changeling" ).test (card );
89+ }
7790 }
7891
7992 private static final class StatFilter {
0 commit comments