add an AF_MustBlock (for things like Target creature blocks CARDNAME this turn if able.)

-also fixes an issue with Card.ChosenColor property
This commit is contained in:
slapshot5
2011-10-15 18:09:27 +00:00
parent 4d0ac9e6e4
commit ff070ee1d5
5 changed files with 285 additions and 1 deletions

View File

@@ -96,6 +96,7 @@ public class Card extends GameEntity implements Comparable<Card> {
private boolean dealtDmgToHumanThisTurn = false; private boolean dealtDmgToHumanThisTurn = false;
private boolean dealtDmgToComputerThisTurn = false; private boolean dealtDmgToComputerThisTurn = false;
private boolean sirenAttackOrDestroy = false; private boolean sirenAttackOrDestroy = false;
private ArrayList<Card> mustBlockCards = new ArrayList<Card>();
private boolean canMorph = false; private boolean canMorph = false;
private boolean faceDown = false; private boolean faceDown = false;
@@ -650,6 +651,38 @@ public class Card extends GameEntity implements Comparable<Card> {
public final boolean getSirenAttackOrDestroy() { public final boolean getSirenAttackOrDestroy() {
return sirenAttackOrDestroy; return sirenAttackOrDestroy;
} }
/**
* a Card that this Card must block if able in an upcoming combat.
* This is cleared at the end of each turn.
*
* @param o Card to block
*
* @since 1.1.6
*/
public void addMustBlockCard(Card c) {
mustBlockCards.add(c);
}
/**
* get the Card that this Card must block this combat
*
* @return the Cards to block (if able)
*
* @since 1.1.6
*/
public ArrayList<Card> getMustBlockCards() {
return mustBlockCards;
}
/**
* clear the list of Cards that this Card must block this combat
*
* @since 1.1.6
*/
public void clearMustBlockCards() {
mustBlockCards.clear();
}
/** /**
* <p>Getter for the field <code>clones</code>.</p> * <p>Getter for the field <code>clones</code>.</p>
@@ -5058,7 +5091,8 @@ public class Card extends GameEntity implements Comparable<Card> {
if (Property.startsWith("non") && (CardUtil.getColors(this).size() == 1 && !isColorless())) return false; if (Property.startsWith("non") && (CardUtil.getColors(this).size() == 1 && !isColorless())) return false;
if (!Property.startsWith("non") && (CardUtil.getColors(this).size() > 1 || isColorless())) return false; if (!Property.startsWith("non") && (CardUtil.getColors(this).size() > 1 || isColorless())) return false;
} else if (Property.equals("ChosenColor")) { } else if (Property.equals("ChosenColor")) {
if (!CardUtil.getColors(this).contains(source.getChosenColor())) return false; //Should this match All chosen colors, or any? Default to first chosen for now until it matters.
if (!CardUtil.getColors(this).contains(source.getChosenColor().get(0))) return false;
} else if (Property.startsWith("YouCtrl")) { } else if (Property.startsWith("YouCtrl")) {
if (!getController().isPlayer(sourceController)) return false; if (!getController().isPlayer(sourceController)) return false;
} else if (Property.startsWith("YouDontCtrl")) { } else if (Property.startsWith("YouDontCtrl")) {

View File

@@ -560,6 +560,8 @@ public class ComputerUtil_Block2 {
setBlockedButUnkilled(new CardList()); //keeps track of all blocked attackers that currently wouldn't be destroyed setBlockedButUnkilled(new CardList()); //keeps track of all blocked attackers that currently wouldn't be destroyed
CardList blockers; CardList blockers;
CardList chumpBlockers; CardList chumpBlockers;
setupForcedBlocks(combat);
setDiff(AllZone.getComputerPlayer().getLife() * 2 - 5); //This is the minimal gain for an unnecessary trade setDiff(AllZone.getComputerPlayer().getLife() * 2 - 5); //This is the minimal gain for an unnecessary trade
@@ -642,4 +644,19 @@ public class ComputerUtil_Block2 {
return combat; return combat;
} }
private static void setupForcedBlocks(Combat combat) {
CardList blockers = AllZoneUtil.getCreaturesInPlay(combat.getDefendingPlayer());
for (Card blocker : blockers) {
if (!blocker.getMustBlockCards().isEmpty()) {
ArrayList<Card> blocks = blocker.getMustBlockCards();
for (Card attacker : blocks) {
if (attacker.isAttacking() && CombatUtil.canBlock(attacker, blocker)) {
combat.addBlocker(attacker, blocker);
getBlockersLeft().remove(blocker);
}
}
}
}
}
} }

View File

@@ -254,6 +254,7 @@ public class EndOfTurn implements java.io.Serializable {
CardList all2 = AllZoneUtil.getCardsIn(Zone.Battlefield); CardList all2 = AllZoneUtil.getCardsIn(Zone.Battlefield);
for (Card c : all2) { for (Card c : all2) {
c.clearMustBlockCards();
if (c.getCreatureAttackedThisTurn()) { if (c.getCreatureAttackedThisTurn()) {
c.setCreatureAttackedThisTurn(false); c.setCreatureAttackedThisTurn(false);
} }

View File

@@ -1050,6 +1050,16 @@ public class AbilityFactory {
} }
} }
else if (API.equals("MustBlock")) {
if (isAb) {
SA = AbilityFactory_Combat.createAbilityMustBlock(this);
} else if (isSp) {
SA = AbilityFactory_Combat.createSpellMustBlock(this);
} else if (isDb) {
SA = AbilityFactory_Combat.createDrawbackMustBlock(this);
}
}
else if (API.equals("Charm")) { else if (API.equals("Charm")) {
if (isAb) { if (isAb) {
SA = AbilityFactory_Charm.createAbilityCharm(this); SA = AbilityFactory_Charm.createAbilityCharm(this);

View File

@@ -665,5 +665,227 @@ public final class AbilityFactory_Combat {
} }
} //mustAttackResolve() } //mustAttackResolve()
//**************************************************************
//*********************** MustBlock ****************************
//**************************************************************
//AB$ MustBlock | Cost$ R T | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Select target creature defending player controls | DefinedAttacker$ Self | SpellDescription$ ...
/**
* <p>createAbilityMustBlock.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*
* @since 1.1.6
*/
public static SpellAbility createAbilityMustBlock(final AbilityFactory af) {
final SpellAbility abMustBlock = new Ability_Activated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = 4237190949098526123L;
@Override
public String getStackDescription() {
return mustBlockStackDescription(af, this);
}
@Override
public boolean canPlayAI() {
return mustBlockCanPlayAI(af, this);
}
@Override
public void resolve() {
mustBlockResolve(af, this);
}
@Override
public boolean doTrigger(final boolean mandatory) {
return mustBlockDoTriggerAI(af, this, mandatory);
}
};
return abMustBlock;
}
/**
* <p>createSpellMustBlock.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*
* @since 1.1.6
*/
public static SpellAbility createSpellMustBlock(final AbilityFactory af) {
final SpellAbility spMustBlock = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = 6758785067306305860L;
@Override
public String getStackDescription() {
return mustBlockStackDescription(af, this);
}
@Override
public boolean canPlayAI() {
return mustBlockCanPlayAI(af, this);
}
@Override
public void resolve() {
mustBlockResolve(af, this);
}
};
return spMustBlock;
}
/**
* <p>createDrawbackMustBlock.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*
* @since 1.1.6
*/
public static SpellAbility createDrawbackMustBlock(final AbilityFactory af) {
final SpellAbility dbMustBlock = new Ability_Sub(af.getHostCard(), af.getAbTgt()) {
private static final long serialVersionUID = -815813765448972775L;
@Override
public void resolve() {
mustBlockResolve(af, this);
}
@Override
public boolean chkAI_Drawback() {
return mustBlockPlayDrawbackAI(af, this);
}
@Override
public boolean doTrigger(final boolean mandatory) {
return mustBlockDoTriggerAI(af, this, mandatory);
}
};
return dbMustBlock;
}
private static String mustBlockStackDescription(final AbilityFactory af, final SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
Card host = af.getHostCard();
StringBuilder sb = new StringBuilder();
if (sa instanceof Ability_Sub) {
sb.append(" ");
} else {
sb.append(sa.getSourceCard()).append(" - ");
}
//end standard pre-
ArrayList<Card> tgtCards;
Target tgt = af.getAbTgt();
if (tgt != null) {
tgtCards = tgt.getTargetCards();
} else {
tgtCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
}
String attacker = null;
if (params.containsKey("DefinedAttacker")) {
ArrayList<Card> cards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("DefinedAttacker"), sa);
attacker = cards.get(0).toString();
}
else {
attacker = host.toString();
}
for (Card c : tgtCards) {
sb.append(c).append(" must block ").append(attacker).append(" if able.");
}
//begin standard post-
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
sb.append(abSub.getStackDescription());
}
return sb.toString();
}
private static boolean mustBlockCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
//disabled for the AI until he/she can make decisions about who to make block
return false;
}
private static boolean mustBlockPlayDrawbackAI(final AbilityFactory af, final SpellAbility sa) {
// AI should only activate this during Human's turn
boolean chance;
//TODO - implement AI
chance = false;
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null) {
chance &= subAb.chkAI_Drawback();
}
return chance;
}
private static boolean mustBlockDoTriggerAI(final AbilityFactory af, final SpellAbility sa,
final boolean mandatory)
{
// If there is a cost payment it's usually not mandatory
if (!ComputerUtil.canPayCost(sa) && !mandatory) {
return false;
}
boolean chance;
//TODO - implement AI
chance = false;
// check SubAbilities DoTrigger?
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
return chance && abSub.doTrigger(mandatory);
}
return chance;
}
private static void mustBlockResolve(final AbilityFactory af, final SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
Card host = af.getHostCard();
ArrayList<Card> tgtCards;
Target tgt = af.getAbTgt();
if (tgt != null) {
tgtCards = tgt.getTargetCards();
} else {
tgtCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
}
ArrayList<Card> cards;
if (params.containsKey("DefinedAttacker")) {
cards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("DefinedAttacker"), sa);
}
else {
cards = new ArrayList<Card>();
cards.add(host);
}
for (final Card c : tgtCards) {
if (tgt == null || CardFactoryUtil.canTarget(sa, c)) {
Card attacker = cards.get(0);
c.addMustBlockCard(attacker);
System.out.println(c+ " is adding "+attacker+" to mustBlockCards: "+c.getMustBlockCards());
}
}
} //mustBlockResolve()
} //end class AbilityFactory_Combat } //end class AbilityFactory_Combat