- Simplified handling of hasFizzled

- Fizzling will now remove Targets that don't have the same timestamp in their current form as the one that was targeted
This commit is contained in:
Sol
2012-07-27 01:41:11 +00:00
parent 8bacf744c9
commit 974e5f5282
2 changed files with 104 additions and 40 deletions

View File

@@ -124,6 +124,63 @@ public class TargetChoices {
return false; return false;
} }
/**
* <p>
* removeTarget.
* </p>
*
* @param card
* a {@link forge.Card} object.
* @return a boolean.
*/
public final boolean removeTarget(final Card card) {
// Do I decrement numTargeted for fizzling targets?
if (!this.targetCards.contains(card)) {
this.targetCards.remove(card);
//this.numTargeted--;
return true;
}
return false;
}
/**
* <p>
* removeTarget.
* </p>
*
* @param pl
* a {@link forge.game.player.Player} object.
* @return a boolean.
*/
public final boolean removeTarget(final Player pl) {
// Do I decrement numTargeted for fizzling targets?
if (!this.targetPlayers.contains(pl)) {
this.targetPlayers.remove(pl);
//this.numTargeted--;
return true;
}
return false;
}
/**
* <p>
* removeTarget.
* </p>
*
* @param sa
* a {@link forge.card.spellability.SpellAbility} object.
* @return a boolean.
*/
public final boolean removeTarget(final SpellAbility sa) {
// Do I decrement numTargeted for fizzling targets?
if (!this.targetSAs.contains(sa)) {
this.targetSAs.remove(sa);
//this.numTargeted--;
return true;
}
return false;
}
/** /**
* <p> * <p>
* Getter for the field <code>targetCards</code>. * Getter for the field <code>targetCards</code>.

View File

@@ -1171,61 +1171,68 @@ public class MagicStack extends MyObservable {
* @return a boolean. * @return a boolean.
*/ */
public final boolean hasFizzled(final SpellAbility sa, final Card source) { public final boolean hasFizzled(final SpellAbility sa, final Card source) {
// By default this has not fizzled // Can't fizzle unless there are some targets
boolean fizzle = false; boolean fizzle = false;
boolean firstTarget = true; Target tgt = sa.getTarget();
if (tgt != null) {
SpellAbility fizzSA = sa; if (tgt.getMinTargets(source, sa) == 0 && tgt.getNumTargeted() == 0) {
// Nothing targeted, and nothing needs to be targeted.
while (true) {
final Target tgt = fizzSA.getTarget();
if ((tgt != null) && (tgt.getMinTargets(source, fizzSA) == 0) && (tgt.getNumTargeted() == 0)) {
// Don't assume fizzled for minTargets == 0 and nothing is
// targeted
} else if (firstTarget
&& ((tgt != null) || (fizzSA.getTargetCard() != null) || (fizzSA.getTargetPlayer() != null))) {
// If there is at least 1 target, fizzle switches because ALL
// targets need to be invalid
fizzle = true;
firstTarget = false;
} }
else {
if (tgt != null) { // Some targets were chosen, fizzling for this subability is now possible
fizzle = true;
// With multi-targets, as long as one target is still legal, // With multi-targets, as long as one target is still legal,
// we'll try to go through as much as possible // we'll try to go through as much as possible
final ArrayList<Object> tgts = tgt.getTargets(); final ArrayList<Object> tgts = tgt.getTargets();
final TargetChoices choices = tgt.getTargetChoices();
for (final Object o : tgts) { for (final Object o : tgts) {
boolean invalidTarget = false;
if (o instanceof Player) { if (o instanceof Player) {
final Player p = (Player) o; final Player p = (Player) o;
fizzle &= !(p.canBeTargetedBy(fizzSA)); invalidTarget = !(p.canBeTargetedBy(sa));
// TODO Remove target?
if (invalidTarget) {
choices.removeTarget(p);
}
} }
if (o instanceof Card) { else if (o instanceof Card) {
final Card card = (Card) o; final Card card = (Card) o;
fizzle &= !(CardFactoryUtil.isTargetStillValid(fizzSA, card)); Card current = AllZoneUtil.getCardState(card);
}
if (o instanceof SpellAbility) {
final SpellAbility tgtSA = (SpellAbility) o;
fizzle &= !(TargetSelection.matchSpellAbility(fizzSA, tgtSA, tgt));
}
}
} else if (fizzSA.getTargetCard() != null) {
// Fizzling will only work for Abilities that use the Target
// class,
// since the info isn't available otherwise
fizzle &= !CardFactoryUtil.isTargetStillValid(fizzSA, fizzSA.getTargetCard());
} else if (fizzSA.getTargetPlayer() != null) {
fizzle &= !fizzSA.getTargetPlayer().canBeTargetedBy(fizzSA);
}
if (fizzSA.getSubAbility() != null) { invalidTarget = current.getTimestamp() != card.getTimestamp();
fizzSA = fizzSA.getSubAbility();
} else { invalidTarget |= !(CardFactoryUtil.isTargetStillValid(sa, card));
break;
if (invalidTarget) {
choices.removeTarget(card);
}
// Remove targets
}
else if (o instanceof SpellAbility) {
final SpellAbility tgtSA = (SpellAbility) o;
invalidTarget = !(TargetSelection.matchSpellAbility(sa, tgtSA, tgt));
// TODO Remove target?
if (invalidTarget) {
choices.removeTarget(tgtSA);
}
}
fizzle &= invalidTarget;
}
} }
} }
else if (sa.getTargetCard() != null) {
fizzle = !CardFactoryUtil.isTargetStillValid(sa, sa.getTargetCard());
}
else if (sa.getTargetPlayer() != null) {
fizzle = !sa.getTargetPlayer().canBeTargetedBy(sa);
}
return fizzle; if (sa.getSubAbility() == null) {
return fizzle;
}
return hasFizzled(sa.getSubAbility(), source) && fizzle;
} }
/** /**