Skip to content
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

LinkedAbilities V2 #143

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion forge-game/src/main/java/forge/game/CardTraitBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import java.util.Map;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import forge.card.CardStateName;
Expand Down Expand Up @@ -35,6 +37,8 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView,
protected Card hostCard;
protected CardState cardState = null;

protected List<StaticLayerInterface> grantedByStatic = Lists.newArrayList();

/** The map params. */
protected Map<String, String> originalMapParams = Maps.newHashMap(),
mapParams = Maps.newHashMap();
Expand Down Expand Up @@ -589,6 +593,31 @@ public Card getOriginalHost() {
return null;
}

public Card getOriginalOrHost() {
return ObjectUtils.defaultIfNull(getOriginalHost(), getHostCard());
}

public List<StaticLayerInterface> getGrantedByStatic() {
return grantedByStatic;
}

public void setGrantedByStatic(List<StaticLayerInterface> list) {
this.grantedByStatic = Lists.newArrayList(list);
}

public void addGrantedByStatic(final StaticLayerInterface stAb) {
grantedByStatic.add(stAb);
}

// TODO currently Clone effects doesn't set Grantor like giving Abilities does
// if it would, then this needs to be refactored anyway
public Card getFirstGrantor() {
if (grantedByStatic.isEmpty()) {
return null;
}
return grantedByStatic.get(0).getHostCard();
}

public boolean isCopiedTrait() {
if (this.getCardState() == null) {
return false;
Expand Down Expand Up @@ -650,7 +679,8 @@ protected void copyHelper(CardTraitBase copy, Card host) {
copy.mapParams = Maps.newHashMap(originalMapParams);
copy.setSVars(sVars);
copy.setCardState(cardState);
// dont use setHostCard to not trigger the not copied parts yet
copy.setGrantedByStatic(grantedByStatic);
// don't use setHostCard to not trigger the not copied parts yet
copy.hostCard = host;
}

Expand Down
8 changes: 8 additions & 0 deletions forge-game/src/main/java/forge/game/StaticLayerInterface.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package forge.game;

import forge.game.card.Card;

public interface StaticLayerInterface {

public Card getHostCard();
}
6 changes: 3 additions & 3 deletions forge-game/src/main/java/forge/game/ability/AbilityUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ public static CardCollection getDefinedCards(final Card hostCard, final String d
}
else if (defined.equals("OriginalHost")) {
if (sa instanceof SpellAbility) {
c = ((SpellAbility)sa).getRootAbility().getOriginalHost();
c = ((SpellAbility)sa).getRootAbility().getFirstGrantor();
} else {
c = sa.getOriginalHost();
c = sa.getFirstGrantor();
}
}
else if (defined.equals("EffectSource")) {
Expand Down Expand Up @@ -539,7 +539,7 @@ else if (ability != null) {
val = 0;
}
} else if (calcX[0].equals("OriginalHost")) {
val = xCount(ability.getOriginalHost(), calcX[1], ability);
val = xCount(ability.getFirstGrantor(), calcX[1], ability);
} else if (calcX[0].startsWith("Remembered")) {
// Add whole Remembered list to handlePaid
final CardCollection list = new CardCollection();
Expand Down
15 changes: 8 additions & 7 deletions forge-game/src/main/java/forge/game/card/ActivationTable.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
package forge.game.card;

import java.util.List;

import org.apache.commons.lang3.ObjectUtils;

import com.google.common.base.Optional;
import com.google.common.collect.ForwardingTable;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;

import forge.game.StaticLayerInterface;
import forge.game.spellability.SpellAbility;
import forge.game.staticability.StaticAbility;

public class ActivationTable extends ForwardingTable<SpellAbility, Optional<StaticAbility>, Integer> {
Table<SpellAbility, Optional<StaticAbility>, Integer> dataTable = HashBasedTable.create();
public class ActivationTable extends ForwardingTable<SpellAbility, List<StaticLayerInterface>, Integer> {
Table<SpellAbility, List<StaticLayerInterface>, Integer> dataTable = HashBasedTable.create();

@Override
protected Table<SpellAbility, Optional<StaticAbility>, Integer> delegate() {
protected Table<SpellAbility, List<StaticLayerInterface>, Integer> delegate() {
return dataTable;
}

Expand All @@ -36,7 +37,7 @@ public void add(SpellAbility sa) {
SpellAbility original = getOriginal(sa);

if (original != null) {
Optional<StaticAbility> st = Optional.fromNullable(root.getGrantorStatic());
List<StaticLayerInterface> st = root.getGrantedByStatic();

delegate().put(original, st, ObjectUtils.defaultIfNull(get(original, st), 0) + 1);
}
Expand All @@ -45,7 +46,7 @@ public void add(SpellAbility sa) {
public Integer get(SpellAbility sa) {
SpellAbility root = sa.getRootAbility();
SpellAbility original = getOriginal(sa);
Optional<StaticAbility> st = Optional.fromNullable(root.getGrantorStatic());
List<StaticLayerInterface> st = root.getGrantedByStatic();

if (contains(original, st)) {
return get(original, st);
Expand Down
118 changes: 33 additions & 85 deletions forge-game/src/main/java/forge/game/card/Card.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import forge.game.GameStage;
import forge.game.GlobalRuleChange;
import forge.game.IHasSVars;
import forge.game.StaticLayerInterface;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
Expand Down Expand Up @@ -74,6 +75,7 @@
import forge.util.collect.FCollectionView;
import io.sentry.Breadcrumb;
import io.sentry.Sentry;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.apache.commons.lang3.tuple.Pair;
Expand Down Expand Up @@ -149,11 +151,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private final Table<Long, Long, CardTraitChanges> changedCardTraits = TreeBasedTable.create(); // Layer 6

// stores the card traits created by static abilities
private final Table<StaticAbility, String, SpellAbility> storedSpellAbilility = TreeBasedTable.create();
private final Table<StaticAbility, String, SpellAbility> storedSpellAbility = TreeBasedTable.create();
private final Table<StaticAbility, String, Trigger> storedTrigger = TreeBasedTable.create();
private final Table<StaticAbility, String, ReplacementEffect> storedReplacementEffect = TreeBasedTable.create();
private final Table<StaticAbility, String, StaticAbility> storedStaticAbility = TreeBasedTable.create();

private final Table<StaticLayerInterface, SpellAbility, SpellAbility> copiedSpellAbility = HashBasedTable.create();

// x=timestamp y=StaticAbility id
private final Table<Long, Long, CardColor> changedCardColorsByText = TreeBasedTable.create(); // Layer 3 by Text Change
private final Table<Long, Long, CardColor> changedCardColorsCharacterDefining = TreeBasedTable.create(); // Layer 5 CDA
Expand Down Expand Up @@ -329,11 +333,8 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private final ActivationTable numberGameActivations = new ActivationTable();
private final ActivationTable numberAbilityResolved = new ActivationTable();

private final Map<SpellAbility, List<String>> chosenModesTurn = Maps.newHashMap();
private final Map<SpellAbility, List<String>> chosenModesGame = Maps.newHashMap();

private final Table<SpellAbility, StaticAbility, List<String>> chosenModesTurnStatic = HashBasedTable.create();
private final Table<SpellAbility, StaticAbility, List<String>> chosenModesGameStatic = HashBasedTable.create();
private final LinkedAbilityTable<String> chosenModesTurn = new LinkedAbilityTable<String>();
private final LinkedAbilityTable<String> chosenModesGame = new LinkedAbilityTable<String>();

private CombatLki combatLKI;

Expand Down Expand Up @@ -4254,12 +4255,12 @@ public final void addChangedCardTraitsByText(Collection<SpellAbility> spells,
}

public final SpellAbility getSpellAbilityForStaticAbility(final String str, final StaticAbility stAb) {
SpellAbility result = storedSpellAbilility.get(stAb, str);
SpellAbility result = storedSpellAbility.get(stAb, str);
if (result == null) {
result = AbilityFactory.getAbility(str, this, stAb);
result.setIntrinsic(false);
result.setGrantorStatic(stAb);
storedSpellAbilility.put(stAb, str, result);
result.addGrantedByStatic(stAb);
storedSpellAbility.put(stAb, str, result);
}
return result;
}
Expand All @@ -4268,6 +4269,7 @@ public final Trigger getTriggerForStaticAbility(final String str, final StaticAb
Trigger result = storedTrigger.get(stAb, str);
if (result == null) {
result = TriggerHandler.parseTrigger(str, this, false, stAb);
result.addGrantedByStatic(stAb);
storedTrigger.put(stAb, str, result);
}
return result;
Expand All @@ -4278,6 +4280,7 @@ public final ReplacementEffect getReplacementEffectForStaticAbility(final String
ReplacementEffect result = storedReplacementEffect.get(stAb, str);
if (result == null) {
result = ReplacementHandler.parseReplacement(str, this, false, stAb);
result.addGrantedByStatic(stAb);
storedReplacementEffect.put(stAb, str, result);
}
return result;
Expand All @@ -4287,11 +4290,28 @@ public final StaticAbility getStaticAbilityForStaticAbility(final String str, fi
StaticAbility result = storedStaticAbility.get(stAb, str);
if (result == null) {
result = StaticAbility.create(str, this, stAb.getCardState(), false);
result.addGrantedByStatic(stAb);
storedStaticAbility.put(stAb, str, result);
}
return result;
}

public final SpellAbility copySpellAbilityForStaticAbility(final SpellAbility sa, final StaticAbility stAb, final boolean intrinsic) {
SpellAbility result = copiedSpellAbility.get(stAb, sa);
if (result == null) {
result = sa.copy(this, false);
if (stAb.hasParam("GainsAbilitiesLimitPerTurn")) {
result.setRestrictions(sa.getRestrictions());
result.getRestrictions().setLimitToCheck(stAb.getParam("GainsAbilitiesLimitPerTurn"));
}
result.setOriginalAbility(sa.getOriginalAbility()); // need to be set to get the Once Per turn Clause correct
result.addGrantedByStatic(stAb);
result.setIntrinsic(intrinsic);
copiedSpellAbility.put(stAb, sa, result);
}
return result;
}

public final void addChangedCardTraits(Collection<SpellAbility> spells, Collection<SpellAbility> removedAbilities,
Collection<Trigger> trigger, Collection<ReplacementEffect> replacements, Collection<StaticAbility> statics,
boolean removeAll, boolean removeNonMana, long timestamp, long staticId) {
Expand Down Expand Up @@ -6863,91 +6883,19 @@ public void resetAbilityResolvedThisTurn() {
}

public List<String> getChosenModesTurn(SpellAbility ability) {
SpellAbility original = null;
SpellAbility root = ability.getRootAbility();

// because trigger spell abilities are copied, try to get original one
if (root.isTrigger()) {
original = root.getTrigger().getOverridingAbility();
} else {
original = ability.getOriginalAbility();
if (original == null) {
original = ability;
}
}

if (ability.getGrantorStatic() != null) {
return chosenModesTurnStatic.get(original, ability.getGrantorStatic());
}
return chosenModesTurn.get(original);
return chosenModesTurn.get(ability);
}
public List<String> getChosenModesGame(SpellAbility ability) {
SpellAbility original = null;
SpellAbility root = ability.getRootAbility();

// because trigger spell abilities are copied, try to get original one
if (root.isTrigger()) {
original = root.getTrigger().getOverridingAbility();
} else {
original = ability.getOriginalAbility();
if (original == null) {
original = ability;
}
}

if (ability.getGrantorStatic() != null) {
return chosenModesGameStatic.get(original, ability.getGrantorStatic());
}
return chosenModesGame.get(original);
return chosenModesGame.get(ability);
}

public void addChosenModes(SpellAbility ability, String mode) {
SpellAbility original = null;
SpellAbility root = ability.getRootAbility();

// because trigger spell abilities are copied, try to get original one
if (root.isTrigger()) {
original = root.getTrigger().getOverridingAbility();
} else {
original = ability.getOriginalAbility();
if (original == null) {
original = ability;
}
}

if (ability.getGrantorStatic() != null) {
List<String> result = chosenModesTurnStatic.get(original, ability.getGrantorStatic());
if (result == null) {
result = Lists.newArrayList();
chosenModesTurnStatic.put(original, ability.getGrantorStatic(), result);
}
result.add(mode);
result = chosenModesGameStatic.get(original, ability.getGrantorStatic());
if (result == null) {
result = Lists.newArrayList();
chosenModesGameStatic.put(original, ability.getGrantorStatic(), result);
}
result.add(mode);
} else {
List<String> result = chosenModesTurn.get(original);
if (result == null) {
result = Lists.newArrayList();
chosenModesTurn.put(original, result);
}
result.add(mode);

result = chosenModesGame.get(original);
if (result == null) {
result = Lists.newArrayList();
chosenModesGame.put(original, result);
}
result.add(mode);
}
this.chosenModesTurn.put(mode, ability);
this.chosenModesGame.put(mode, ability);
}

public void resetChosenModeTurn() {
chosenModesTurn.clear();
chosenModesTurnStatic.clear();
}

public int getPlaneswalkerAbilityActivated() {
Expand Down
Loading