package forge;
import forge.card.cardFactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility;
import java.util.Random;
/**
* <p>AIPlayer class.</p>
*
* @author Forge
* @version $Id: $
*/
public class AIPlayer extends Player {
/**
* <p>Constructor for AIPlayer.</p>
*
* @param myName a {@link java.lang.String} object.
*/
public AIPlayer(String myName) {
this(myName, 20, 0);
}
/**
* <p>Constructor for AIPlayer.</p>
*
* @param myName a {@link java.lang.String} object.
* @param myLife a int.
* @param myPoisonCounters a int.
*/
public AIPlayer(String myName, int myLife, int myPoisonCounters) {
super(myName, myLife, myPoisonCounters);
}
/**
* <p>getOpponent.</p>
*
* @return a {@link forge.Player} object.
*/
public Player getOpponent() {
return AllZone.getHumanPlayer();
}
////////////////
///
/// Methods to ease transition to Abstract Player class
///
///////////////
/**
* <p>isHuman.</p>
*
* @return a boolean.
*/
public boolean isHuman() {
return false;
}
/**
* <p>isComputer.</p>
*
* @return a boolean.
*/
public boolean isComputer() {
return true;
}
/** {@inheritDoc} */
public boolean isPlayer(Player p1) {
return p1.getName().equals(this.name);
}
///////////////
///
/// End transition methods
///
///////////////
////////////////////////////////
///
/// replaces AllZone.getGameAction().draw* methods
///
////////////////////////////////
/** {@inheritDoc} */
public CardList mayDrawCard() {
return mayDrawCards(1);
}
/** {@inheritDoc} */
public CardList mayDrawCards(int n) {
if (AllZone.getComputerLibrary().size() > n) {
return drawCards(n);
}
else return new CardList();
}
/**
* <p>dredge.</p>
*
* @return a boolean.
*/
public boolean dredge() {
CardList dredgers = getDredge();
Random random = MyRandom.random;
//use dredge if there are more than one of them in your graveyard
if (dredgers.size() > 1 || (dredgers.size() == 1 && random.nextBoolean())) {
dredgers.shuffle();
Card c = dredgers.get(0);
//rule 702.49a
if (getDredgeNumber(c) <= AllZone.getComputerLibrary().size()) {
//dredge library, put card in hand
AllZone.getGameAction().moveToHand(c);
//put dredge number in graveyard
for (int i = 0; i < getDredgeNumber(c); i++) {
Card c2 = AllZone.getComputerLibrary().get(0);
AllZone.getGameAction().moveToGraveyard(c2);
}
return true;
}
}
return false;
}
////////////////////////////////
///
/// replaces AllZone.getGameAction().discard* methods
///
////////////////////////////////
/** {@inheritDoc} */
public CardList discard(final int num, final SpellAbility sa, boolean duringResolution) {
int max = AllZoneUtil.getPlayerHand(this).size();
max = Math.min(max, num);
CardList discarded = new CardList();
for (int i = 0; i < max; i++) {
CardList hand = AllZoneUtil.getPlayerHand(this);
if (hand.size() > 0) {
CardList basicLandsInPlay = AllZoneUtil.getPlayerTypeInPlay(this, "Basic");
if (basicLandsInPlay.size() > 5) {
CardList basicLandsInHand = hand.getType("Basic");
if (basicLandsInHand.size() > 0) {
discarded.add(hand.get(0));
doDiscard(basicLandsInHand.get(CardUtil.getRandomIndex(basicLandsInHand)), sa);
} else {
CardListUtil.sortAttackLowFirst(hand);
CardListUtil.sortNonFlyingFirst(hand);
discarded.add(hand.get(0));
doDiscard(hand.get(0), sa);
}
} else {
CardListUtil.sortCMC(hand);
discarded.add(hand.get(0));
doDiscard(hand.get(0), sa);
}
}
}
return discarded;
}//end discard
/** {@inheritDoc} */
public void discardUnless(int num, String uType, SpellAbility sa) {
CardList hand = AllZoneUtil.getPlayerHand(this);
CardList tHand = hand.getType(uType);
if (tHand.size() > 0) {
CardListUtil.sortCMC(tHand);
tHand.reverse();
tHand.get(0).getController().discard(tHand.get(0), sa); //this got changed to doDiscard basically
return;
}
AllZone.getComputerPlayer().discard(num, sa, false);
}
/** {@inheritDoc} */
public void handToLibrary(final int numToLibrary, final String libPosIn) {
String libPos = libPosIn;
for (int i = 0; i < numToLibrary; i++) {
int position;
if (libPos.equalsIgnoreCase("Top"))
position = 0;
else if (libPos.equalsIgnoreCase("Bottom"))
position = -1;
else {
Random r = MyRandom.random;
if (r.nextBoolean())
position = 0;
else
position = -1;
}
CardList hand = AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer());
CardList blIP = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
blIP = blIP.getType("Basic");
if (blIP.size() > 5) {
CardList blIH = hand.getType("Basic");
if (blIH.size() > 0) {
Card card = blIH.get(CardUtil.getRandomIndex(blIH));
AllZone.getGameAction().moveToLibrary(card, position);
} else {
CardListUtil.sortAttackLowFirst(hand);
CardListUtil.sortNonFlyingFirst(hand);
AllZone.getGameAction().moveToLibrary(hand.get(0), position);
}
} else {
CardListUtil.sortCMC(hand);
AllZone.getGameAction().moveToLibrary(hand.get(0), position);
}
}
}
///////////////////////////
/** {@inheritDoc} */
protected void doScry(final CardList topN, final int N) {
int num = N;
for (int i = 0; i < num; i++) {
boolean bottom = false;
if (topN.get(i).isBasicLand()) {
CardList bl = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
bl = bl.filter(new CardListFilter() {
public boolean addCard(Card c) {
if (c.isBasicLand()) return true;
return false;
}
});
bottom = bl.size() > 5; // if control more than 5 Basic land, probably don't need more
} else if (topN.get(i).isCreature()) {
CardList cl = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
cl = cl.filter(new CardListFilter() {
public boolean addCard(Card c) {
if (c.isCreature()) return true;
return false;
}
});
bottom = cl.size() > 5; // if control more than 5 Creatures, probably don't need more
}
if (bottom) {
Card c = topN.get(i);
AllZone.getGameAction().moveToBottomOfLibrary(c);
//topN.remove(c);
}
}
num = topN.size();
for (int i = 0; i < num; i++) // put the rest on top in random order
{
Random rndm = MyRandom.random;
int r = rndm.nextInt(topN.size());
Card c = topN.get(r);
AllZone.getGameAction().moveToLibrary(c);
topN.remove(r);
}
}
/** {@inheritDoc} */
public void sacrificePermanent(String prompt, CardList choices) {
if (choices.size() > 0) {
//TODO - this could probably use better AI
Card c = CardFactoryUtil.AI_getWorstPermanent(choices, false, false, false, false);
AllZone.getGameAction().sacrificeDestroy(c);
}
}
/** {@inheritDoc} */
protected void clashMoveToTopOrBottom(Card c) {
//computer just puts the card back until such time it can make a smarter decision
AllZone.getGameAction().moveToLibrary(c);
}
@Override
protected void discard_Chains_of_Mephistopheles() {
discard(null);
drawCard();
}
}//end AIPlayer class