ColorSet: add combine function (#8960)

This commit is contained in:
Hans Mackowiak
2025-10-20 09:45:57 +02:00
committed by GitHub
parent a8d494d2d8
commit 5efd7e6e7c
16 changed files with 49 additions and 39 deletions

View File

@@ -235,7 +235,7 @@ public final class CardRules implements ICardCharacteristics {
public ColorSet getColor() { public ColorSet getColor() {
switch (splitType.getAggregationMethod()) { switch (splitType.getAggregationMethod()) {
case COMBINE: case COMBINE:
return ColorSet.fromMask(mainPart.getColor().getColor() | otherPart.getColor().getColor()); return ColorSet.combine(mainPart.getColor(), otherPart.getColor());
default: default:
return mainPart.getColor(); return mainPart.getColor();
} }

View File

@@ -123,6 +123,14 @@ public enum ColorSet implements Iterable<Color>, Serializable {
return fromMask(mana.getColorProfile()); return fromMask(mana.getColorProfile());
} }
public static ColorSet combine(final ColorSet... colors) {
byte mask = 0;
for (ColorSet c : colors) {
mask |= c.getColor();
}
return fromMask(mask);
}
/** /**
* Checks for any color. * Checks for any color.
* *

View File

@@ -19,8 +19,9 @@ package forge.game;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import forge.card.ColorSet;
import forge.card.GamePieceType; import forge.card.GamePieceType;
import forge.card.MagicColor;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
@@ -787,7 +788,7 @@ public final class GameActionUtil {
eff.setOwner(controller); eff.setOwner(controller);
eff.setImageKey(sourceCard.getImageKey()); eff.setImageKey(sourceCard.getImageKey());
eff.setColor(MagicColor.COLORLESS); eff.setColor(ColorSet.C);
eff.setGamePieceType(GamePieceType.EFFECT); eff.setGamePieceType(GamePieceType.EFFECT);
// try to get the SpellAbility from the mana ability // try to get the SpellAbility from the mana ability
//eff.setEffectSource((SpellAbility)null); //eff.setEffectSource((SpellAbility)null);

View File

@@ -6,8 +6,8 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Table; import com.google.common.collect.Table;
import forge.GameCommand; import forge.GameCommand;
import forge.card.CardRarity; import forge.card.CardRarity;
import forge.card.ColorSet;
import forge.card.GamePieceType; import forge.card.GamePieceType;
import forge.card.MagicColor;
import forge.game.Game; import forge.game.Game;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.GameObject; import forge.game.GameObject;
@@ -617,10 +617,10 @@ public abstract class SpellAbilityEffect {
if (name.startsWith("Emblem")) { if (name.startsWith("Emblem")) {
eff.setEmblem(true); eff.setEmblem(true);
// Emblem needs to be colorless // Emblem needs to be colorless
eff.setColor(MagicColor.COLORLESS); eff.setColor(ColorSet.C);
eff.setRarity(CardRarity.Common); eff.setRarity(CardRarity.Common);
} else { } else {
eff.setColor(hostCard.getColor().getColor()); eff.setColor(hostCard.getColor());
eff.setRarity(hostCard.getRarity()); eff.setRarity(hostCard.getRarity());
} }

View File

@@ -4409,9 +4409,9 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
} }
public final void setColor(final String... color) { public final void setColor(final String... color) {
setColor(ColorSet.fromNames(color).getColor()); setColor(ColorSet.fromNames(color));
} }
public final void setColor(final byte color) { public final void setColor(final ColorSet color) {
currentState.setColor(color); currentState.setColor(color);
} }
@@ -4419,7 +4419,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
return getColor(currentState); return getColor(currentState);
} }
public final ColorSet getColor(CardState state) { public final ColorSet getColor(CardState state) {
byte colors = state.getColor(); byte colors = state.getColor().getColor();
for (final CardColor cc : Iterables.concat(changedCardColorsByText.values(), changedCardColorsCharacterDefining.values(), changedCardColors.values())) { for (final CardColor cc : Iterables.concat(changedCardColorsByText.values(), changedCardColorsCharacterDefining.values(), changedCardColors.values())) {
if (cc.additional()) { if (cc.additional()) {
colors |= cc.color().getColor(); colors |= cc.color().getColor();

View File

@@ -303,7 +303,7 @@ public class CardCopyService {
newCopy.setCounters(Maps.newHashMap(copyFrom.getCounters())); newCopy.setCounters(Maps.newHashMap(copyFrom.getCounters()));
newCopy.setColor(copyFrom.getColor().getColor()); newCopy.setColor(copyFrom.getColor());
newCopy.setPhasedOut(copyFrom.getPhasedOut()); newCopy.setPhasedOut(copyFrom.getPhasedOut());
newCopy.setTapped(copyFrom.isTapped()); newCopy.setTapped(copyFrom.isTapped());
newCopy.setTributed(copyFrom.isTributed()); newCopy.setTributed(copyFrom.isTributed());

View File

@@ -339,12 +339,10 @@ public class CardFactory {
card.setName(rules.getName()); card.setName(rules.getName());
// Combined mana cost // Combined mana cost
ManaCost combinedManaCost = ManaCost.combine(rules.getMainPart().getManaCost(), rules.getOtherPart().getManaCost()); card.setManaCost(rules.getManaCost());
card.setManaCost(combinedManaCost);
// Combined card color // Combined card color
final byte combinedColor = (byte) (rules.getMainPart().getColor().getColor() | rules.getOtherPart().getColor().getColor()); card.setColor(rules.getColor());
card.setColor(combinedColor);
card.setType(new CardType(rules.getType())); card.setType(new CardType(rules.getType()));
// Combined text based on Oracle text - might not be necessary // Combined text based on Oracle text - might not be necessary
@@ -407,7 +405,7 @@ public class CardFactory {
// Super and 'middle' types should use enums. // Super and 'middle' types should use enums.
c.setType(new CardType(face.getType())); c.setType(new CardType(face.getType()));
c.setColor(face.getColor().getColor()); c.setColor(face.getColor());
if (face.getIntPower() != Integer.MAX_VALUE) { if (face.getIntPower() != Integer.MAX_VALUE) {
c.setBasePower(face.getIntPower()); c.setBasePower(face.getIntPower());
@@ -593,11 +591,11 @@ public class CardFactory {
} }
if (cause.hasParam("AddColors")) { if (cause.hasParam("AddColors")) {
state.addColor(colors.getColor()); state.addColor(colors);
} }
if (cause.hasParam("SetColor") || cause.hasParam("SetColorByManaCost")) { if (cause.hasParam("SetColor") || cause.hasParam("SetColorByManaCost")) {
state.setColor(colors.getColor()); state.setColor(colors);
} }
if (cause.hasParam("NonLegendary")) { if (cause.hasParam("NonLegendary")) {

View File

@@ -60,7 +60,7 @@ public class CardState implements GameObject, IHasSVars, ITranslatable {
private String name = ""; private String name = "";
private CardType type = new CardType(false); private CardType type = new CardType(false);
private ManaCost manaCost = ManaCost.NO_COST; private ManaCost manaCost = ManaCost.NO_COST;
private byte color = MagicColor.COLORLESS; private ColorSet color = ColorSet.C;
private String oracleText = ""; private String oracleText = "";
private String functionalVariantName = null; private String functionalVariantName = null;
private int basePower = 0; private int basePower = 0;
@@ -191,14 +191,14 @@ public class CardState implements GameObject, IHasSVars, ITranslatable {
view.updateManaCost(this); view.updateManaCost(this);
} }
public final byte getColor() { public final ColorSet getColor() {
return color; return color;
} }
public final void addColor(final byte color) { public final void addColor(final ColorSet color) {
this.color |= color; this.color = ColorSet.combine(this.color, color);
view.updateColors(card); view.updateColors(card);
} }
public final void setColor(final byte color) { public final void setColor(final ColorSet color) {
this.color = color; this.color = color;
view.updateColors(card); view.updateColors(card);
} }

View File

@@ -1308,7 +1308,7 @@ public class CardView extends GameEntityView {
set(TrackableProperty.Colors, c.getColor()); set(TrackableProperty.Colors, c.getColor());
} }
void updateColors(CardState c) { void updateColors(CardState c) {
set(TrackableProperty.Colors, ColorSet.fromMask(c.getColor())); set(TrackableProperty.Colors, c.getColor());
} }
void setOriginalColors(Card c) { void setOriginalColors(Card c) {
set(TrackableProperty.OriginalColors, c.getColor()); set(TrackableProperty.OriginalColors, c.getColor());

View File

@@ -6,8 +6,11 @@ import com.google.common.collect.Lists;
import forge.ImageKeys; import forge.ImageKeys;
import forge.StaticData; import forge.StaticData;
import forge.card.CardType; import forge.card.CardType;
import forge.card.ColorSet;
import forge.card.GamePieceType; import forge.card.GamePieceType;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostParser;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
@@ -32,14 +35,14 @@ public class TokenInfo {
final String[] intrinsicKeywords; final String[] intrinsicKeywords;
final int basePower; final int basePower;
final int baseToughness; final int baseToughness;
final String color; final ColorSet color;
public TokenInfo(Card c) { public TokenInfo(Card c) {
// TODO: Figure out how to handle legacy images? // TODO: Figure out how to handle legacy images?
this.name = c.getName(); this.name = c.getName();
this.imageName = ImageKeys.getTokenImageName(c.getImageKey()); this.imageName = ImageKeys.getTokenImageName(c.getImageKey());
this.manaCost = c.getManaCost().toString(); this.manaCost = c.getManaCost().toString();
this.color = MagicColor.toShortString(c.getCurrentState().getColor()); this.color = c.getCurrentState().getColor();
this.types = getCardTypes(c); this.types = getCardTypes(c);
List<String> list = Lists.newArrayList(); List<String> list = Lists.newArrayList();
@@ -60,7 +63,7 @@ public class TokenInfo {
String[] types = null; String[] types = null;
String[] keywords = null; String[] keywords = null;
String imageName = null; String imageName = null;
String color = ""; ColorSet color = null;
for (String info : tokenInfo) { for (String info : tokenInfo) {
int index = info.indexOf(':'); int index = info.indexOf(':');
if (index == -1) { if (index == -1) {
@@ -80,7 +83,7 @@ public class TokenInfo {
} else if (info.startsWith("Image:")) { } else if (info.startsWith("Image:")) {
imageName = remainder; imageName = remainder;
} else if (info.startsWith("Color:")) { } else if (info.startsWith("Color:")) {
color = remainder; color = ColorSet.fromNames(remainder);
} }
} }
@@ -115,7 +118,7 @@ public class TokenInfo {
c.setName(name); c.setName(name);
c.setImageKey(ImageKeys.getTokenKey(imageName)); c.setImageKey(ImageKeys.getTokenKey(imageName));
c.setColor(color.isEmpty() ? manaCost : color); c.setColor(color == null ? ColorSet.fromManaCost(new ManaCost(new ManaCostParser(manaCost))) : color);
c.setGamePieceType(GamePieceType.TOKEN); c.setGamePieceType(GamePieceType.TOKEN);
for (final String t : types) { for (final String t : types) {
@@ -189,7 +192,7 @@ public class TokenInfo {
} }
} }
result.setColor(color); result.setColor(ColorSet.fromMask(color));
} }
} }
if (!typeMap.isEmpty()) { if (!typeMap.isEmpty()) {

View File

@@ -253,7 +253,7 @@ public class AbilityManaPart implements java.io.Serializable {
eff.setOwner(sourceCard.getController()); eff.setOwner(sourceCard.getController());
eff.setImageKey(sourceCard.getImageKey()); eff.setImageKey(sourceCard.getImageKey());
eff.setColor(MagicColor.COLORLESS); eff.setColor(ColorSet.C);
eff.setGamePieceType(GamePieceType.EFFECT); eff.setGamePieceType(GamePieceType.EFFECT);
String cantcounterstr = "Event$ Counter | ValidSA$ Spell.IsRemembered | Description$ That spell can't be countered."; String cantcounterstr = "Event$ Counter | ValidSA$ Spell.IsRemembered | Description$ That spell can't be countered.";

View File

@@ -623,7 +623,7 @@ public final class StaticAbilityContinuous {
// Mana cost // Mana cost
affectedCard.addChangedManaCost(state.getManaCost(), se.getTimestamp(), stAb.getId()); affectedCard.addChangedManaCost(state.getManaCost(), se.getTimestamp(), stAb.getId());
// color // color
affectedCard.addColorByText(ColorSet.fromMask(state.getColor()), se.getTimestamp(), stAb); affectedCard.addColorByText(state.getColor(), se.getTimestamp(), stAb);
// type // type
affectedCard.addChangedCardTypesByText(new CardType(state.getType()), se.getTimestamp(), stAb.getId()); affectedCard.addChangedCardTypesByText(new CardType(state.getType()), se.getTimestamp(), stAb.getId());
// abilities // abilities

View File

@@ -34,9 +34,9 @@ public class CardThemedCommanderDeckBuilder extends CardThemedDeckBuilder {
this.availableList.removeAll(aiPlayables); this.availableList.removeAll(aiPlayables);
targetSize=format.getMainRange().getMinimum(); targetSize=format.getMainRange().getMinimum();
colors = keyCard.getRules().getColorIdentity(); colors = keyCard.getRules().getColorIdentity();
colors = ColorSet.fromMask(colors.getColor() | keyCard.getRules().getColorIdentity().getColor()); colors = ColorSet.combine(colors, keyCard.getRules().getColorIdentity());
if (secondKeyCard != null && !format.equals(DeckFormat.Oathbreaker)) { if (secondKeyCard != null && !format.equals(DeckFormat.Oathbreaker)) {
colors = ColorSet.fromMask(colors.getColor() | secondKeyCard.getRules().getColorIdentity().getColor()); colors = ColorSet.combine(colors, secondKeyCard.getRules().getColorIdentity());
targetSize--; targetSize--;
} }
numSpellsNeeded = ((Double)Math.floor(targetSize*(getCreaturePercentage()+getSpellPercentage()))).intValue(); numSpellsNeeded = ((Double)Math.floor(targetSize*(getCreaturePercentage()+getSpellPercentage()))).intValue();

View File

@@ -39,9 +39,9 @@ public class CardThemedConquestDeckBuilder extends CardThemedDeckBuilder {
this.availableList.removeAll(aiPlayables); this.availableList.removeAll(aiPlayables);
targetSize=format.getMainRange().getMinimum(); targetSize=format.getMainRange().getMinimum();
colors = keyCard.getRules().getColorIdentity(); colors = keyCard.getRules().getColorIdentity();
colors = ColorSet.fromMask(colors.getColor() | keyCard.getRules().getColorIdentity().getColor()); colors = ColorSet.combine(colors, keyCard.getRules().getColorIdentity());
if(secondKeyCard!=null) { if(secondKeyCard!=null) {
colors = ColorSet.fromMask(colors.getColor() | secondKeyCard.getRules().getColorIdentity().getColor()); colors = ColorSet.combine(colors, secondKeyCard.getRules().getColorIdentity());
targetSize--; targetSize--;
} }
numSpellsNeeded = ((Double)Math.floor(targetSize*(getCreaturePercentage()+getSpellPercentage()))).intValue(); numSpellsNeeded = ((Double)Math.floor(targetSize*(getCreaturePercentage()+getSpellPercentage()))).intValue();

View File

@@ -133,11 +133,11 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase {
System.out.println("Pre Colors: " + colors.toEnumSet().toString()); System.out.println("Pre Colors: " + colors.toEnumSet().toString());
} }
if(!colors.hasAllColors(keyCard.getRules().getColorIdentity().getColor())){ if(!colors.hasAllColors(keyCard.getRules().getColorIdentity().getColor())){
colors = ColorSet.fromMask(colors.getColor() | keyCard.getRules().getColorIdentity().getColor()); colors = ColorSet.combine(colors, keyCard.getRules().getColorIdentity());
} }
if(secondKeyCard!=null) { if(secondKeyCard!=null) {
if (!colors.hasAllColors(secondKeyCard.getRules().getColorIdentity().getColor())) { if (!colors.hasAllColors(secondKeyCard.getRules().getColorIdentity().getColor())) {
colors = ColorSet.fromMask(colors.getColor() | secondKeyCard.getRules().getColorIdentity().getColor()); colors = ColorSet.combine(colors, secondKeyCard.getRules().getColorIdentity());
} }
} }
numSpellsNeeded = ((Double)Math.floor(targetSize*(getCreaturePercentage()+getSpellPercentage()))).intValue(); numSpellsNeeded = ((Double)Math.floor(targetSize*(getCreaturePercentage()+getSpellPercentage()))).intValue();
@@ -462,7 +462,7 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase {
// Want a card that has just one "off" color. // Want a card that has just one "off" color.
final ColorSet off = colors.getOffColors(card.getRules().getColor()); final ColorSet off = colors.getOffColors(card.getRules().getColor());
if (off.isMonoColor()) { if (off.isMonoColor()) {
colors = ColorSet.fromMask(colors.getColor() | off.getColor()); colors = ColorSet.combine(colors, off);
break; break;
} }
} }

View File

@@ -484,7 +484,7 @@ public class LimitedDeckBuilder extends DeckGeneratorBase {
// Want a card that has just one "off" color. // Want a card that has just one "off" color.
final ColorSet off = colors.getOffColors(card.getRules().getColor()); final ColorSet off = colors.getOffColors(card.getRules().getColor());
if (off.isMonoColor()) { if (off.isMonoColor()) {
colors = ColorSet.fromMask(colors.getColor() | off.getColor()); colors = ColorSet.combine(colors, off);
break; break;
} }
} }