package forge.card.abilityFactory;
import forge.*;
import forge.card.spellability.*;
import forge.gui.GuiUtils;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Random;
/**
* <p>AbilityFactory_Reveal class.</p>
*
* @author Forge
* @version $Id: $
*/
public class AbilityFactory_Reveal {
// *************************************************************************
// ************************* Dig *******************************************
// *************************************************************************
/**
* <p>createAbilityDig.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createAbilityDig(final AbilityFactory af) {
final SpellAbility abDig = new Ability_Activated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = 4239474096624403497L;
@Override
public String getStackDescription() {
return digStackDescription(af, this);
}
public boolean canPlayAI() {
return digCanPlayAI(af, this);
}
@Override
public void resolve() {
digResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return digTriggerAI(af, this, mandatory);
}
};
return abDig;
}
/**
* <p>createSpellDig.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createSpellDig(final AbilityFactory af) {
final SpellAbility spDig = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = 3389143507816474146L;
@Override
public String getStackDescription() {
return digStackDescription(af, this);
}
public boolean canPlayAI() {
return digCanPlayAI(af, this);
}
@Override
public void resolve() {
digResolve(af, this);
}
};
return spDig;
}
/**
* <p>createDrawbackDig.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createDrawbackDig(final AbilityFactory af) {
final SpellAbility dbDig = new Ability_Sub(af.getHostCard(), af.getAbTgt()) {
private static final long serialVersionUID = -3372788479421357024L;
@Override
public String getStackDescription() {
return digStackDescription(af, this);
}
@Override
public void resolve() {
digResolve(af, this);
}
@Override
public boolean chkAI_Drawback() {
return true;
}
@Override
public boolean doTrigger(boolean mandatory) {
return digTriggerAI(af, this, mandatory);
}
};
return dbDig;
}
/**
* <p>digStackDescription.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a {@link java.lang.String} object.
*/
private static String digStackDescription(AbilityFactory af, SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
Card host = af.getHostCard();
StringBuilder sb = new StringBuilder();
int numToDig = AbilityFactory.calculateAmount(af.getHostCard(), params.get("DigNum"), sa);
if (!(sa instanceof Ability_Sub))
sb.append(sa.getSourceCard()).append(" - ");
else
sb.append(" ");
ArrayList<Player> tgtPlayers;
Target tgt = af.getAbTgt();
if (tgt != null)
tgtPlayers = tgt.getTargetPlayers();
else
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
sb.append(host.getController()).append(" looks at the top ").append(numToDig);
sb.append(" card");
if (numToDig != 1) sb.append("s");
sb.append(" of ");
if (tgtPlayers.contains(host.getController())) {
sb.append("his or her ");
} else {
for (Player p : tgtPlayers) {
sb.append(p).append("'s ");
}
}
sb.append("library.");
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
sb.append(abSub.getStackDescription());
}
return sb.toString();
}
/**
* <p>digCanPlayAI.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a boolean.
*/
private static boolean digCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
Card source = sa.getSourceCard();
if (!ComputerUtil.canPayCost(sa))
return false;
double chance = .4; // 40 percent chance with instant speed stuff
if (AbilityFactory.isSorcerySpeed(sa))
chance = .667; // 66.7% chance for sorcery speed (since it will never activate EOT)
Random r = MyRandom.random;
boolean randomReturn = r.nextFloat() <= Math.pow(chance, source.getAbilityUsed() + 1);
Target tgt = sa.getTarget();
Player libraryOwner = AllZone.getComputerPlayer();
if (sa.getTarget() != null) {
tgt.resetTargets();
if (!AllZone.getHumanPlayer().canTarget(source))
return false;
else
sa.getTarget().addTarget(AllZone.getHumanPlayer());
libraryOwner = AllZone.getHumanPlayer();
}
//return false if nothing to dig into
if (AllZoneUtil.getCardsInZone(Constant.Zone.Library, libraryOwner).isEmpty())
return false;
if (AbilityFactory.playReusable(sa))
randomReturn = true;
if (af.hasSubAbility()) {
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
return randomReturn && abSub.chkAI_Drawback();
}
}
return randomReturn;
}
/**
* <p>digTriggerAI.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @param mandatory a boolean.
* @return a boolean.
*/
private static boolean digTriggerAI(final AbilityFactory af, final SpellAbility sa, boolean mandatory) {
if (!ComputerUtil.canPayCost(sa))
return false;
Target tgt = sa.getTarget();
if (sa.getTarget() != null) {
tgt.resetTargets();
sa.getTarget().addTarget(AllZone.getComputerPlayer());
}
return true;
}
/**
* <p>digResolve.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
*/
private static void digResolve(final AbilityFactory af, final SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
Card host = af.getHostCard();
Player player = sa.getActivatingPlayer();
int numToDig = AbilityFactory.calculateAmount(af.getHostCard(), params.get("DigNum"), sa);
String destZone1 = params.containsKey("DestinationZone") ? params.get("DestinationZone") : "Hand";
int libraryPosition = params.containsKey("LibraryPosition") ? Integer.parseInt(params.get("LibraryPosition")) : -1;
int destZone1ChangeNum = 1;
boolean mitosis = params.containsKey("Mitosis");
String changeValid = params.containsKey("ChangeValid") ? params.get("ChangeValid") : "";
boolean anyNumber = params.containsKey("AnyNumber");
String destZone2 = params.containsKey("DestinationZone2") ? params.get("DestinationZone2") : "Library";
int libraryPosition2 = params.containsKey("LibraryPosition2") ? Integer.parseInt(params.get("LibraryPosition2")) : -1;
boolean optional = params.containsKey("Optional");
boolean noMove = params.containsKey("NoMove");
boolean changeAll = false;
ArrayList<String> keywords = new ArrayList<String>();
if (params.containsKey("Keywords")) {
keywords.addAll(Arrays.asList(params.get("Keywords").split(" & ")));
}
if (params.containsKey("ChangeNum")) {
if (params.get("ChangeNum").equalsIgnoreCase("All")) changeAll = true;
else destZone1ChangeNum = Integer.parseInt(params.get("ChangeNum"));
}
ArrayList<Player> tgtPlayers;
Target tgt = af.getAbTgt();
if (tgt != null)
tgtPlayers = tgt.getTargetPlayers();
else
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
for (Player p : tgtPlayers) {
if (tgt == null || p.canTarget(af.getHostCard())) {
CardList top = new CardList();
CardList valid = new CardList();
CardList rest = new CardList();
PlayerZone library = AllZone.getZone(Constant.Zone.Library, p);
numToDig = Math.min(numToDig, library.size());
for (int i = 0; i < numToDig; i++) {
top.add(library.get(i));
}
if (top.size() > 0) {
Card dummy = new Card();
dummy.setName("[No valid cards]");
if (params.containsKey("Reveal")) {
GuiUtils.getChoice("Revealing cards from library", top.toArray());
//AllZone.getGameAction().revealToCopmuter(top.toArray()); - for when it exists
} else if (player.isHuman()) {
//show the user the revealed cards
GuiUtils.getChoice("Looking at cards from library", top.toArray());
}
if (!noMove) {
if (mitosis) {
valid = sharesNameWithCardOnBattlefield(top);
for (Card c : top) {
if (!valid.contains(c)) rest.add(c);
}
} else if (!changeValid.equals("")) {
if (changeValid.contains("ChosenType")) {
changeValid = changeValid.replace("ChosenType", host.getChosenType());
}
valid = top.getValidCards(changeValid.split(","), host.getController(), host);
for (Card c : top) {
if (!valid.contains(c)) rest.add(c);
}
if (valid.isEmpty()) {
valid.add(dummy);
}
} else {
valid = top;
}
if (changeAll) {
for (Card c : valid) {
if (c.equals(dummy)) continue;
PlayerZone zone = AllZone.getZone(destZone1, c.getOwner());
if (zone.is("Library")) {
AllZone.getGameAction().moveToLibrary(c, libraryPosition);
} else {
AllZone.getGameAction().moveTo(zone, c);
}
}
} else {
int j = 0;
if (player.isHuman()) {
while (j < destZone1ChangeNum || (anyNumber && j < numToDig)) {
//let user get choice
Card chosen = null;
String prompt = "Choose a card to put into the ";
if (destZone1.equals("Library") && libraryPosition == -1)
prompt = "Put the rest on the bottom of the ";
if (destZone1.equals("Library") && libraryPosition == 0)
prompt = "Put the rest on top of the ";
if (anyNumber || optional) {
chosen = GuiUtils.getChoiceOptional(prompt + destZone1, valid.toArray());
} else {
chosen = GuiUtils.getChoice(prompt + destZone1, valid.toArray());
}
if (chosen == null || chosen.getName().equals("[No valid cards]")) break;
valid.remove(chosen);
PlayerZone zone = AllZone.getZone(destZone1, chosen.getOwner());
if (zone.is("Library")) {
//System.out.println("Moving to lib position: "+libraryPosition);
AllZone.getGameAction().moveToLibrary(chosen, libraryPosition);
} else {
Card c = AllZone.getGameAction().moveTo(zone, chosen);
if (destZone1.equals("Battlefield") && !keywords.isEmpty())
for (String kw : keywords) c.addExtrinsicKeyword(kw);
}
//AllZone.getGameAction().revealToComputer() - for when this exists
j++;
}
}//human
else { //computer (pick the first cards)
int changeNum = Math.min(destZone1ChangeNum, valid.size());
if (anyNumber) changeNum = valid.size();//always take all
for (j = 0; j < changeNum; j++) {
Card chosen = valid.get(0);
if (chosen.equals(dummy)) break;
PlayerZone zone = AllZone.getZone(destZone1, chosen.getOwner());
if (zone.is("Library")) {
AllZone.getGameAction().moveToLibrary(chosen, libraryPosition);
} else {
AllZone.getGameAction().moveTo(zone, chosen);
if (destZone1.equals("Battlefield") && !keywords.isEmpty())
for (String kw : keywords) chosen.addExtrinsicKeyword(kw);
}
if (changeValid.length() > 0)
GuiUtils.getChoice("Computer picked: ", chosen);
valid.remove(chosen);
}
}
}
//dump anything not selected from valid back into the rest
if (!changeAll) rest.addAll(valid);
if (rest.contains(dummy)) rest.remove(dummy);
//now, move the rest to destZone2
if (destZone2.equals("Library")) {
if(player.isHuman()) {
//put them in any order
while (rest.size() > 0) {
Card chosen;
if (rest.size() > 1) {
String prompt = "Put the rest on top of the library in any order";
if (libraryPosition2 == -1)
prompt = "Put the rest on the bottom of the library in any order";
chosen = GuiUtils.getChoice(prompt, rest.toArray());
} else {
chosen = rest.get(0);
}
AllZone.getGameAction().moveToLibrary(chosen, libraryPosition2);
rest.remove(chosen);
}
} else { //Computer
for (int i = 0; i < rest.size(); i++) {
AllZone.getGameAction().moveToLibrary(rest.get(i), libraryPosition2);
}
}
} else {
//just move them randomly
for (int i = 0; i < rest.size(); i++) {
Card c = rest.get(i);
PlayerZone toZone = AllZone.getZone(destZone2, c.getOwner());
c = AllZone.getGameAction().moveTo(toZone, c);
if (destZone2.equals("Battlefield") && !keywords.isEmpty()) {
for (String kw : keywords) c.addExtrinsicKeyword(kw);
}
}
}
}
}//end if canTarget
}//end foreach player
}
}//end resolve
//returns a CardList that is a subset of list with cards that share a name with a permanent on the battlefield
/**
* <p>sharesNameWithCardOnBattlefield.</p>
*
* @param list a {@link forge.CardList} object.
* @return a {@link forge.CardList} object.
*/
private static CardList sharesNameWithCardOnBattlefield(CardList list) {
CardList toReturn = new CardList();
CardList play = AllZoneUtil.getCardsInPlay();
for (Card c : list) {
for (Card p : play) {
if (p.getName().equals(c.getName())) toReturn.add(c);
}
}
return toReturn;
}
//**********************************************************************
//******************************* RevealHand ***************************
//**********************************************************************
/**
* <p>createAbilityRevealHand.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createAbilityRevealHand(final AbilityFactory af) {
final SpellAbility abRevealHand = new Ability_Activated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = 2785654059206102004L;
@Override
public String getStackDescription() {
return revealHandStackDescription(af, this);
}
@Override
public boolean canPlayAI() {
return revealHandCanPlayAI(af, this);
}
@Override
public void resolve() {
revealHandResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return revealHandTrigger(af, this, mandatory);
}
};
return abRevealHand;
}
/**
* <p>createSpellRevealHand.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createSpellRevealHand(final AbilityFactory af) {
final SpellAbility spRevealHand = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = -668943560971904791L;
@Override
public String getStackDescription() {
return revealHandStackDescription(af, this);
}
@Override
public boolean canPlayAI() {
return revealHandCanPlayAI(af, this);
}
@Override
public void resolve() {
revealHandResolve(af, this);
}
};
return spRevealHand;
}
/**
* <p>createDrawbackRevealHand.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createDrawbackRevealHand(final AbilityFactory af) {
final SpellAbility dbRevealHand = new Ability_Sub(af.getHostCard(), af.getAbTgt()) {
private static final long serialVersionUID = -6079668770576878801L;
@Override
public String getStackDescription() {
// when getStackDesc is called, just build exactly what is happening
return revealHandStackDescription(af, this);
}
@Override
public void resolve() {
revealHandResolve(af, this);
}
@Override
public boolean chkAI_Drawback() {
return revealHandTargetAI(af, this, false, false);
}
@Override
public boolean doTrigger(boolean mandatory) {
return revealHandTrigger(af, this, mandatory);
}
};
return dbRevealHand;
}
/**
* <p>revealHandStackDescription.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a {@link java.lang.String} object.
*/
private static String revealHandStackDescription(AbilityFactory af, SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
StringBuilder sb = new StringBuilder();
if (!(sa instanceof Ability_Sub))
sb.append(sa.getSourceCard()).append(" - ");
else
sb.append(" ");
ArrayList<Player> tgtPlayers;
Target tgt = af.getAbTgt();
if (tgt != null)
tgtPlayers = tgt.getTargetPlayers();
else
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
sb.append(sa.getActivatingPlayer()).append(" looks at ");
if (tgtPlayers.size() > 0) {
for (Player p : tgtPlayers)
sb.append(p.toString()).append("'s ");
} else {
sb.append("Error - no target players for RevealHand. ");
}
sb.append("hand.");
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
sb.append(abSub.getStackDescription());
}
return sb.toString();
}
/**
* <p>revealHandCanPlayAI.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a boolean.
*/
private static boolean revealHandCanPlayAI(final AbilityFactory af, SpellAbility sa) {
// AI cannot use this properly until he can use SAs during Humans turn
if (!ComputerUtil.canPayCost(sa))
return false;
Card source = sa.getSourceCard();
Cost abCost = af.getAbCost();
if (abCost != null) {
// AI currently disabled for these costs
if (abCost.getSacCost()) {
return false;
}
if (abCost.getLifeCost()) {
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
return false;
}
if (abCost.getDiscardCost()) return false;
if (abCost.getSubCounter()) {
if (abCost.getCounterType().equals(Counters.P1P1)) return false; // Other counters should be used
}
}
boolean bFlag = revealHandTargetAI(af, sa, true, false);
if (!bFlag)
return false;
Random r = MyRandom.random;
boolean randomReturn = r.nextFloat() <= Math.pow(.667, source.getAbilityUsed() + 1);
if (AbilityFactory.playReusable(sa))
randomReturn = true;
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
randomReturn &= subAb.chkAI_Drawback();
return randomReturn;
}
/**
* <p>revealHandTargetAI.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @param primarySA a boolean.
* @param mandatory a boolean.
* @return a boolean.
*/
private static boolean revealHandTargetAI(AbilityFactory af, SpellAbility sa, boolean primarySA, boolean mandatory) {
Target tgt = af.getAbTgt();
Card source = sa.getSourceCard();
int humanHandSize = AllZoneUtil.getPlayerHand(AllZone.getHumanPlayer()).size();
if (tgt != null) {
// ability is targeted
tgt.resetTargets();
boolean canTgtHuman = AllZone.getHumanPlayer().canTarget(source);
if (!canTgtHuman || humanHandSize == 0)
return false;
else
tgt.addTarget(AllZone.getHumanPlayer());
} else {
//if it's just defined, no big deal
}
return true;
}// revealHandTargetAI()
/**
* <p>revealHandTrigger.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @param mandatory a boolean.
* @return a boolean.
*/
private static boolean revealHandTrigger(AbilityFactory af, SpellAbility sa, boolean mandatory) {
if (!ComputerUtil.canPayCost(sa)) // If there is a cost payment
return false;
if (!revealHandTargetAI(af, sa, false, mandatory))
return false;
// check SubAbilities DoTrigger?
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
return abSub.doTrigger(mandatory);
}
return true;
}
/**
* <p>revealHandResolve.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
*/
private static void revealHandResolve(final AbilityFactory af, final SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
ArrayList<Player> tgtPlayers;
Target tgt = af.getAbTgt();
if (tgt != null)
tgtPlayers = tgt.getTargetPlayers();
else
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
for (Player p : tgtPlayers) {
if (tgt == null || p.canTarget(af.getHostCard())) {
CardList hand = AllZoneUtil.getPlayerHand(p);
if (sa.getActivatingPlayer().isHuman()) {
if (hand.size() > 0) {
GuiUtils.getChoice(p + "'s hand", hand.toArray());
} else {
StringBuilder sb = new StringBuilder();
sb.append(p).append("'s hand is empty!");
javax.swing.JOptionPane.showMessageDialog(null, sb.toString(), p + "'s hand", JOptionPane.INFORMATION_MESSAGE);
}
} else {
//reveal to Computer (when computer can keep track of seen cards...)
}
}
}
}
//**********************************************************************
//******************************* SCRY *********************************
//**********************************************************************
/**
* <p>createAbilityScry.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createAbilityScry(final AbilityFactory af) {
final SpellAbility abScry = new Ability_Activated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = 2631175859655699419L;
@Override
public String getStackDescription() {
return scryStackDescription(af, this);
}
public boolean canPlayAI() {
return scryCanPlayAI(af, this);
}
@Override
public void resolve() {
scryResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return scryTriggerAI(af, this);
}
};
return abScry;
}
/**
* <p>createSpellScry.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createSpellScry(final AbilityFactory af) {
final SpellAbility spScry = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = 6273876397392154403L;
@Override
public String getStackDescription() {
return scryStackDescription(af, this);
}
public boolean canPlayAI() {
return scryCanPlayAI(af, this);
}
@Override
public void resolve() {
scryResolve(af, this);
}
};
return spScry;
}
/**
* <p>createDrawbackScry.</p>
*
* @param AF a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createDrawbackScry(final AbilityFactory AF) {
final SpellAbility dbScry = new Ability_Sub(AF.getHostCard(), AF.getAbTgt()) {
private static final long serialVersionUID = 7763043327497404630L;
final AbilityFactory af = AF;
@Override
public String getStackDescription() {
// when getStackDesc is called, just build exactly what is happening
return scryStackDescription(af, this);
}
@Override
public void resolve() {
scryResolve(af, this);
}
@Override
public boolean chkAI_Drawback() {
return scryTargetAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return scryTriggerAI(af, this);
}
};
return dbScry;
}
/**
* <p>scryResolve.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
*/
private static void scryResolve(final AbilityFactory af, final SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
int num = 1;
if (params.containsKey("ScryNum"))
num = AbilityFactory.calculateAmount(sa.getSourceCard(), params.get("ScryNum"), sa);
ArrayList<Player> tgtPlayers;
Target tgt = af.getAbTgt();
if (tgt != null)
tgtPlayers = tgt.getTargetPlayers();
else
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
for (Player p : tgtPlayers) {
if (tgt == null || p.canTarget(af.getHostCard())) {
p.scry(num);
}
}
}
/**
* <p>scryTargetAI.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a boolean.
*/
private static boolean scryTargetAI(AbilityFactory af, SpellAbility sa) {
Target tgt = af.getAbTgt();
if (tgt != null) { // It doesn't appear that Scry ever targets
// ability is targeted
tgt.resetTargets();
tgt.addTarget(AllZone.getComputerPlayer());
}
return true;
}// scryTargetAI()
/**
* <p>scryTriggerAI.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a boolean.
*/
private static boolean scryTriggerAI(AbilityFactory af, SpellAbility sa) {
if (!ComputerUtil.canPayCost(sa))
return false;
return scryTargetAI(af, sa);
}// scryTargetAI()
/**
* <p>scryStackDescription.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a {@link java.lang.String} object.
*/
private static String scryStackDescription(AbilityFactory af, SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
StringBuilder sb = new StringBuilder();
if (!(sa instanceof Ability_Sub))
sb.append(sa.getSourceCard().getName()).append(" - ");
else
sb.append(" ");
ArrayList<Player> tgtPlayers;
Target tgt = af.getAbTgt();
if (tgt != null)
tgtPlayers = tgt.getTargetPlayers();
else
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
for (Player p : tgtPlayers)
sb.append(p.toString()).append(" ");
int num = 1;
if (params.containsKey("ScryNum"))
num = AbilityFactory.calculateAmount(sa.getSourceCard(), params.get("ScryNum"), sa);
sb.append("scrys (").append(num).append(").");
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
sb.append(abSub.getStackDescription());
}
return sb.toString();
}
/**
* <p>scryCanPlayAI.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a boolean.
*/
private static boolean scryCanPlayAI(final AbilityFactory af, SpellAbility sa) {
Card source = sa.getSourceCard();
double chance = .4; // 40 percent chance of milling with instant speed stuff
if (AbilityFactory.isSorcerySpeed(sa))
chance = .667; // 66.7% chance for sorcery speed (since it will never activate EOT)
Random r = MyRandom.random;
boolean randomReturn = r.nextFloat() <= Math.pow(chance, source.getAbilityUsed() + 1);
if (AbilityFactory.playReusable(sa))
randomReturn = true;
if (af.hasSubAbility()) {
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
return randomReturn && abSub.chkAI_Drawback();
}
}
return randomReturn;
}
//**********************************************************************
//*********************** REARRANGETOPOFLIBRARY ************************
//**********************************************************************
/**
* <p>createRearrangeTopOfLibraryAbility.</p>
*
* @param AF a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createRearrangeTopOfLibraryAbility(final AbilityFactory AF) {
final SpellAbility RTOLAbility = new Ability_Activated(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()) {
private static final long serialVersionUID = -548494891203983219L;
@Override
public String getStackDescription() {
return rearrangeTopOfLibraryStackDescription(AF, this);
}
@Override
public boolean canPlayAI() {
return false;
}
@Override
public boolean doTrigger(boolean mandatory) {
return rearrangeTopOfLibraryTrigger(AF, this, mandatory);
}
@Override
public void resolve() {
rearrangeTopOfLibraryResolve(AF, this);
}
};
return RTOLAbility;
}
/**
* <p>createRearrangeTopOfLibrarySpell.</p>
*
* @param AF a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createRearrangeTopOfLibrarySpell(final AbilityFactory AF) {
final SpellAbility RTOLSpell = new Spell(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()) {
private static final long serialVersionUID = 6977502611509431864L;
@Override
public String getStackDescription() {
return rearrangeTopOfLibraryStackDescription(AF, this);
}
@Override
public boolean canPlayAI() {
return false;
}
@Override
public boolean doTrigger(boolean mandatory) {
return rearrangeTopOfLibraryTrigger(AF, this, mandatory);
}
@Override
public void resolve() {
rearrangeTopOfLibraryResolve(AF, this);
}
};
return RTOLSpell;
}
/**
* <p>createRearrangeTopOfLibraryDrawback.</p>
*
* @param AF a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createRearrangeTopOfLibraryDrawback(final AbilityFactory AF) {
final SpellAbility dbDraw = new Ability_Sub(AF.getHostCard(), AF.getAbTgt()) {
private static final long serialVersionUID = -777856059960750319L;
@Override
public String getStackDescription() {
// when getStackDesc is called, just build exactly what is happening
return rearrangeTopOfLibraryStackDescription(AF, this);
}
@Override
public void resolve() {
rearrangeTopOfLibraryResolve(AF, this);
}
@Override
public boolean chkAI_Drawback() {
return false;
}
@Override
public boolean doTrigger(boolean mandatory) {
return rearrangeTopOfLibraryTrigger(AF, this, mandatory);
}
};
return dbDraw;
}
/**
* <p>rearrangeTopOfLibraryStackDescription.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a {@link java.lang.String} object.
*/
private static String rearrangeTopOfLibraryStackDescription(final AbilityFactory af, final SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
int numCards = 0;
ArrayList<Player> tgtPlayers;
boolean shuffle = false;
Target tgt = af.getAbTgt();
if (tgt != null && !params.containsKey("Defined"))
tgtPlayers = tgt.getTargetPlayers();
else
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
numCards = AbilityFactory.calculateAmount(af.getHostCard(), params.get("NumCards"), sa);
shuffle = params.containsKey("MayShuffle") ? true : false;
StringBuilder ret = new StringBuilder();
if (!(sa instanceof Ability_Sub)) {
ret.append(af.getHostCard().getName());
ret.append(" - ");
}
ret.append("Look at the top ");
ret.append(numCards);
ret.append(" cards of ");
for (Player p : tgtPlayers) {
ret.append(p.getName());
ret.append("s");
ret.append(" & ");
}
ret.delete(ret.length() - 3, ret.length());
ret.append(" library. Then put them back in any order.");
if (shuffle) {
ret.append("You may have ");
if (tgtPlayers.size() > 1) {
ret.append("those");
} else {
ret.append("that");
}
ret.append(" player shuffle his or her library.");
}
return ret.toString();
}
/**
* <p>rearrangeTopOfLibraryTrigger.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @param mandatory a boolean.
* @return a boolean.
*/
private static boolean rearrangeTopOfLibraryTrigger(final AbilityFactory af, final SpellAbility sa, final boolean mandatory) {
if (!ComputerUtil.canPayCost(sa))
return false;
Card source = sa.getSourceCard();
Target tgt = af.getAbTgt();
if (tgt != null) {
// ability is targeted
tgt.resetTargets();
boolean canTgtHuman = AllZone.getHumanPlayer().canTarget(source);
if (!canTgtHuman)
return false;
else
tgt.addTarget(AllZone.getHumanPlayer());
} else {
//if it's just defined, no big deal
}
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
return abSub.doTrigger(mandatory);
}
return false;
}
/**
* <p>rearrangeTopOfLibraryResolve.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
*/
private static void rearrangeTopOfLibraryResolve(final AbilityFactory af, final SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
int numCards = 0;
ArrayList<Player> tgtPlayers = new ArrayList<Player>();
boolean shuffle = false;
if (sa.getActivatingPlayer().isHuman()) {
Target tgt = af.getAbTgt();
if (tgt != null && !params.containsKey("Defined"))
tgtPlayers = tgt.getTargetPlayers();
else
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
numCards = AbilityFactory.calculateAmount(af.getHostCard(), params.get("NumCards"), sa);
shuffle = params.containsKey("MayShuffle") ? true : false;
for (Player p : tgtPlayers)
if (tgt == null || p.canTarget(af.getHostCard()))
rearrangeTopOfLibrary(af.getHostCard(), p, numCards, shuffle);
}
}
/**
* use this when Human needs to rearrange the top X cards in a player's library. You
* may also specify a shuffle when done
*
* @param src the source card
* @param player the player to target
* @param numCards the number of cards from the top to rearrange
* @param mayshuffle a boolean.
*/
private static void rearrangeTopOfLibrary(final Card src, final Player player, final int numCards, boolean mayshuffle) {
PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);
int maxCards = lib.size();
maxCards = Math.min(maxCards, numCards);
if (maxCards == 0) return;
CardList topCards = new CardList();
//show top n cards:
for (int j = 0; j < maxCards; j++) {
topCards.add(lib.get(j));
}
for (int i = 1; i <= maxCards; i++) {
String suffix = "";
switch (i) {
case 1:
suffix = "st";
break;
case 2:
suffix = "nd";
break;
case 3:
suffix = "rd";
break;
default:
suffix = "th";
}
String title = "Put " + i + suffix + " from the top: ";
Object o = GuiUtils.getChoiceOptional(title, topCards.toArray());
if (o == null) break;
Card c_1 = (Card) o;
topCards.remove(c_1);
AllZone.getGameAction().moveToLibrary(c_1, i - 1);
}
if (mayshuffle) {
if (GameActionUtil.showYesNoDialog(src, "Do you want to shuffle the library?")) {
player.shuffle();
}
}
}
}//end class AbilityFactory_Reveal