checkstyle

This commit is contained in:
jendave
2011-10-26 07:49:44 +00:00
parent 81244734dd
commit 8a6bde480f
15 changed files with 2762 additions and 1482 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,23 +1,25 @@
package forge;
import forge.Constant.Zone;
import forge.card.cardFactory.CardFactoryUtil;
import forge.card.trigger.Trigger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import forge.Constant.Zone;
import forge.card.cardFactory.CardFactoryUtil;
import forge.card.trigger.Trigger;
//doesHumanAttackAndWin() uses the global variable AllZone.getComputerPlayer()
/**
* <p>ComputerUtil_Attack2 class.</p>
*
* <p>
* ComputerUtil_Attack2 class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class ComputerUtil_Attack2 {
//possible attackers and blockers
// possible attackers and blockers
private CardList attackers;
private CardList blockers;
private CardList playerCreatures;
@@ -26,30 +28,42 @@ public class ComputerUtil_Attack2 {
private Random random = MyRandom.random;
private final int randomInt = random.nextInt();
private CardList humanList; //holds human player creatures
private CardList computerList; //holds computer creatures
private CardList humanList; // holds human player creatures
private CardList computerList; // holds computer creatures
private int aiAggression = 0; // added by Masher, how aggressive the ai attack will be depending on circumstances
private int aiAggression = 0; // added by Masher, how aggressive the ai
// attack will be depending on circumstances
/**
* <p>Constructor for ComputerUtil_Attack2.</p>
*
* @param possibleAttackers an array of {@link forge.Card} objects.
* @param possibleBlockers an array of {@link forge.Card} objects.
* @param blockerLife a int.
* <p>
* Constructor for ComputerUtil_Attack2.
* </p>
*
* @param possibleAttackers
* an array of {@link forge.Card} objects.
* @param possibleBlockers
* an array of {@link forge.Card} objects.
* @param blockerLife
* a int.
*/
public ComputerUtil_Attack2(Card[] possibleAttackers, Card[] possibleBlockers, int blockerLife) {
public ComputerUtil_Attack2(final Card[] possibleAttackers, final Card[] possibleBlockers, final int blockerLife) {
this(new CardList(possibleAttackers), new CardList(possibleBlockers), blockerLife);
}
/**
* <p>Constructor for ComputerUtil_Attack2.</p>
*
* @param possibleAttackers a {@link forge.CardList} object.
* @param possibleBlockers a {@link forge.CardList} object.
* @param blockerLife a int.
* <p>
* Constructor for ComputerUtil_Attack2.
* </p>
*
* @param possibleAttackers
* a {@link forge.CardList} object.
* @param possibleBlockers
* a {@link forge.CardList} object.
* @param blockerLife
* a int.
*/
public ComputerUtil_Attack2(final CardList possibleAttackers, CardList possibleBlockers, int blockerLife) {
public ComputerUtil_Attack2(final CardList possibleAttackers,
final CardList possibleBlockers, final int blockerLife) {
humanList = new CardList(possibleBlockers.toArray());
humanList = humanList.getType("Creature");
@@ -61,18 +75,21 @@ public class ComputerUtil_Attack2 {
attackers = getPossibleAttackers(possibleAttackers);
blockers = getPossibleBlockers(possibleBlockers, attackers);
this.blockerLife = blockerLife;
} //constructor
} // constructor
/**
* <p>sortAttackers.</p>
*
* @param in a {@link forge.CardList} object.
* <p>
* sortAttackers.
* </p>
*
* @param in
* a {@link forge.CardList} object.
* @return a {@link forge.CardList} object.
*/
public final CardList sortAttackers(final CardList in) {
CardList list = new CardList();
//Cards with triggers should come first (for Battle Cry)
// Cards with triggers should come first (for Battle Cry)
for (Card attacker : in) {
ArrayList<Trigger> registeredTriggers = attacker.getTriggers();
for (Trigger trigger : registeredTriggers) {
@@ -90,19 +107,23 @@ public class ComputerUtil_Attack2 {
}
return list;
} //sortAttackers()
} // sortAttackers()
//Is there any reward for attacking? (for 0/1 creatures there is not)
// Is there any reward for attacking? (for 0/1 creatures there is not)
/**
* <p>isEffectiveAttacker.</p>
*
* @param attacker a {@link forge.Card} object.
* @param combat a {@link forge.Combat} object.
* <p>
* isEffectiveAttacker.
* </p>
*
* @param attacker
* a {@link forge.Card} object.
* @param combat
* a {@link forge.Combat} object.
* @return a boolean.
*/
public final boolean isEffectiveAttacker(final Card attacker, Combat combat) {
public final boolean isEffectiveAttacker(final Card attacker, final Combat combat) {
//if the attacker will die when attacking don't attack
// if the attacker will die when attacking don't attack
if (attacker.getNetDefense() + CombatUtil.predictToughnessBonusOfAttacker(attacker, null, combat) <= 0) {
return false;
}
@@ -113,10 +134,10 @@ public class ComputerUtil_Attack2 {
if (CombatUtil.poisonIfUnblocked(attacker, AllZone.getHumanPlayer(), combat) > 0) {
return true;
}
CardList controlledByCompy = AllZone.getComputerPlayer().getAllCards();
for(Card c : controlledByCompy) {
for (Card c : controlledByCompy) {
for (Trigger trigger : c.getTriggers()) {
if (CombatUtil.combatTriggerWillTrigger(attacker, null, trigger, combat)) {
return true;
@@ -128,12 +149,15 @@ public class ComputerUtil_Attack2 {
}
/**
* <p>getPossibleAttackers.</p>
*
* @param in a {@link forge.CardList} object.
* <p>
* getPossibleAttackers.
* </p>
*
* @param in
* a {@link forge.CardList} object.
* @return a {@link forge.CardList} object.
*/
public CardList getPossibleAttackers(CardList in) {
public final CardList getPossibleAttackers(final CardList in) {
CardList list = new CardList(in.toArray());
list = list.filter(new CardListFilter() {
public boolean addCard(final Card c) {
@@ -141,16 +165,20 @@ public class ComputerUtil_Attack2 {
}
});
return list;
} //getPossibleAttackers()
} // getPossibleAttackers()
/**
* <p>getPossibleBlockers.</p>
*
* @param blockers a {@link forge.CardList} object.
* @param attackers a {@link forge.CardList} object.
* <p>
* getPossibleBlockers.
* </p>
*
* @param blockers
* a {@link forge.CardList} object.
* @param attackers
* a {@link forge.CardList} object.
* @return a {@link forge.CardList} object.
*/
public final CardList getPossibleBlockers(CardList blockers, CardList attackers) {
public final CardList getPossibleBlockers(final CardList blockers, CardList attackers) {
CardList possibleBlockers = new CardList(blockers.toArray());
final CardList attackerList = new CardList(attackers.toArray());
possibleBlockers = possibleBlockers.filter(new CardListFilter() {
@@ -167,24 +195,28 @@ public class ComputerUtil_Attack2 {
}
});
return possibleBlockers;
}//getPossibleBlockers()
} // getPossibleBlockers()
//this checks to make sure that the computer player
//doesn't lose when the human player attacks
//this method is used by getAttackers()
// this checks to make sure that the computer player
// doesn't lose when the human player attacks
// this method is used by getAttackers()
/**
* <p>notNeededAsBlockers.</p>
*
* @param attackers a {@link forge.CardList} object.
* @param combat a {@link forge.Combat} object.
* <p>
* notNeededAsBlockers.
* </p>
*
* @param attackers
* a {@link forge.CardList} object.
* @param combat
* a {@link forge.Combat} object.
* @return a {@link forge.CardList} object.
*/
public final CardList notNeededAsBlockers(CardList attackers, Combat combat) {
public final CardList notNeededAsBlockers(final CardList attackers, Combat combat) {
CardList notNeededAsBlockers = new CardList(attackers.toArray());
CardListUtil.sortAttackLowFirst(attackers);
int blockersNeeded = attackers.size();
//don't hold back creatures that can't block any of the human creatures
// don't hold back creatures that can't block any of the human creatures
CardList list = getPossibleBlockers(attackers, humanList);
for (int i = 0; i < list.size(); i++) {
@@ -201,9 +233,11 @@ public class ComputerUtil_Attack2 {
return notNeededAsBlockers;
}
// Increase the total number of blockers needed by 1 if Finest Hour in play
// Increase the total number of blockers needed by 1 if Finest Hour in
// play
// (human will get an extra first attack with a creature that untaps)
// In addition, if the computer guesses it needs no blockers, make sure that
// In addition, if the computer guesses it needs no blockers, make sure
// that
// it won't be surprised by Exalted
int humanExaltedBonus = countExaltedBonus(AllZone.getHumanPlayer());
@@ -212,134 +246,153 @@ public class ComputerUtil_Attack2 {
if ((blockersNeeded == 0 || nFinestHours > 0) && humanList.size() > 0) {
//
// total attack = biggest creature + exalted, *2 if Rafiq is in play
// total attack = biggest creature + exalted, *2 if Rafiq is in
// play
int humanBaseAttack = getAttack(humanList.get(0)) + humanExaltedBonus;
if (nFinestHours > 0) {
// For Finest Hour, one creature could attack and get the bonus TWICE
// For Finest Hour, one creature could attack and get the
// bonus TWICE
humanBaseAttack = humanBaseAttack + humanExaltedBonus;
}
int totalExaltedAttack = AllZoneUtil.isCardInPlay("Rafiq of the Many", AllZone.getHumanPlayer()) ?
2 * humanBaseAttack : humanBaseAttack;
int totalExaltedAttack = AllZoneUtil.isCardInPlay("Rafiq of the Many",
AllZone.getHumanPlayer()) ? 2 * humanBaseAttack : humanBaseAttack;
if ((AllZone.getComputerPlayer().getLife() - 3) <= totalExaltedAttack) {
// We will lose if there is an Exalted attack -- keep one blocker
if (blockersNeeded == 0 && notNeededAsBlockers.size() > 0)
// We will lose if there is an Exalted attack -- keep one
// blocker
if (blockersNeeded == 0 && notNeededAsBlockers.size() > 0) {
notNeededAsBlockers.remove(0);
}
// Finest Hour allows a second Exalted attack: keep a blocker for that too
if (nFinestHours > 0 && notNeededAsBlockers.size() > 0)
// Finest Hour allows a second Exalted attack: keep a
// blocker for that too
if (nFinestHours > 0 && notNeededAsBlockers.size() > 0) {
notNeededAsBlockers.remove(0);
}
}
}
}
//re-add creatures with vigilance
// re-add creatures with vigilance
for (Card c : attackers) {
if (c.hasKeyword("Vigilance"))
if (c.hasKeyword("Vigilance")) {
notNeededAsBlockers.add(c);
}
}
return notNeededAsBlockers;
}
//this uses a global variable, which isn't perfect
// this uses a global variable, which isn't perfect
/**
* <p>doesHumanAttackAndWin.</p>
*
* @param nBlockingCreatures a int.
* <p>
* doesHumanAttackAndWin.
* </p>
*
* @param nBlockingCreatures
* a int.
* @return a boolean.
*/
public boolean doesHumanAttackAndWin(int nBlockingCreatures) {
public final boolean doesHumanAttackAndWin(final int nBlockingCreatures) {
int totalAttack = 0;
int stop = humanList.size() - nBlockingCreatures;
for (int i = 0; i < stop; i++)
for (int i = 0; i < stop; i++) {
totalAttack += getAttack(humanList.get(i));
}
//originally -3 so the computer will try to stay at 3 life
//0 now to prevent the AI from not attacking when it's got low life
//(seems to happen too often)
// originally -3 so the computer will try to stay at 3 life
// 0 now to prevent the AI from not attacking when it's got low life
// (seems to happen too often)
return AllZone.getComputerPlayer().getLife() <= totalAttack;
}
/**
* <p>doAssault.</p>
*
* <p>
* doAssault.
* </p>
*
* @return a boolean.
*/
private boolean doAssault() {
//Beastmaster Ascension
// Beastmaster Ascension
if (AllZoneUtil.isCardInPlay("Beastmaster Ascension", AllZone.getComputerPlayer()) && attackers.size() > 1) {
CardList beastions = AllZone.getComputerPlayer().getCardsIn(Constant.Zone.Battlefield).
getName("Beastmaster Ascension");
CardList beastions = AllZone.getComputerPlayer().getCardsIn(Constant.Zone.Battlefield)
.getName("Beastmaster Ascension");
int minCreatures = 7;
for (Card beastion : beastions) {
int counters = beastion.getCounters(Counters.QUEST);
minCreatures = Math.min(minCreatures, 7 - counters);
}
if (attackers.size() >= minCreatures)
if (attackers.size() >= minCreatures) {
return true;
}
}
//I think this is right but the assault code may still be a little off
// I think this is right but the assault code may still be a little off
CardListUtil.sortAttackLowFirst(attackers);
int totalAttack = 0;
//presumes the Human will block
for (int i = 0; i < (attackers.size() - blockers.size()); i++)
// presumes the Human will block
for (int i = 0; i < (attackers.size() - blockers.size()); i++) {
totalAttack += getAttack(attackers.get(i));
}
return blockerLife <= totalAttack;
}//doAssault()
} // doAssault()
/**
* <p>chooseDefender.</p>
*
* @param c a {@link forge.Combat} object.
* @param bAssault a boolean.
* <p>
* chooseDefender.
* </p>
*
* @param c
* a {@link forge.Combat} object.
* @param bAssault
* a boolean.
*/
public void chooseDefender(Combat c, boolean bAssault) {
// TODO: split attackers to different planeswalker/human
public final void chooseDefender(final Combat c, final boolean bAssault) {
// TODO split attackers to different planeswalker/human
// AI will only attack one Defender per combat for now
ArrayList<Object> defs = c.getDefenders();
// Randomly determine who EVERYONE is attacking
// would be better to determine more individually
int n = MyRandom.random.nextInt(defs.size());
Object entity = AllZone.getComputerPlayer().getMustAttackEntity();
if(null != entity) {
ArrayList<Object> defenders = AllZone.getCombat().getDefenders();
n = defenders.indexOf(entity);
if(-1 == n) {
System.out.println("getMustAttackEntity() returned something not in defenders.");
c.setCurrentDefender(0);
}
else {
c.setCurrentDefender(n);
}
}
else {
if (null != entity) {
ArrayList<Object> defenders = AllZone.getCombat().getDefenders();
n = defenders.indexOf(entity);
if (-1 == n) {
System.out.println("getMustAttackEntity() returned something not in defenders.");
c.setCurrentDefender(0);
} else {
c.setCurrentDefender(n);
}
} else {
if (defs.size() == 1 || bAssault) {
c.setCurrentDefender(0);
} else {
c.setCurrentDefender(n);
}
else c.setCurrentDefender(n);
}
return;
}
/**
* <p>Getter for the field <code>attackers</code>.</p>
*
* <p>
* Getter for the field <code>attackers</code>.
* </p>
*
* @return a {@link forge.Combat} object.
*/
public Combat getAttackers() {
//if this method is called multiple times during a turn,
//it will always return the same value
//randomInt is used so that the computer doesn't always
//do the same thing on turn 3 if he had the same creatures in play
//I know this is a little confusing
// if this method is called multiple times during a turn,
// it will always return the same value
// randomInt is used so that the computer doesn't always
// do the same thing on turn 3 if he had the same creatures in play
// I know this is a little confusing
random.setSeed(AllZone.getPhase().getTurn() + randomInt);
Combat combat = new Combat();
@@ -354,16 +407,15 @@ public class ComputerUtil_Attack2 {
CardList attackersLeft = new CardList(attackers.toArray());
//Attackers that don't really have a choice
// Attackers that don't really have a choice
for (Card attacker : attackers) {
if ((attacker.hasKeyword("CARDNAME attacks each turn if able.")
|| attacker.hasKeyword("At the beginning of the end step, destroy CARDNAME.")
|| attacker.hasKeyword("At the beginning of the end step, exile CARDNAME.")
|| attacker.hasKeyword("At the beginning of the end step, sacrifice CARDNAME.")
|| attacker.getSacrificeAtEOT()
|| attacker.getSirenAttackOrDestroy()
|| (attacker.getController().getMustAttackEntity() != null))
&& CombatUtil.canAttack(attacker, combat)) {
|| attacker.getSacrificeAtEOT() || attacker.getSirenAttackOrDestroy() || (attacker.getController()
.getMustAttackEntity() != null)) && CombatUtil.canAttack(attacker, combat))
{
combat.addAttacker(attacker);
attackersLeft.remove(attacker);
}
@@ -380,19 +432,21 @@ public class ComputerUtil_Attack2 {
// examine the potential forces
CardList nextTurnAttackers = new CardList();
int candidateCounterAttackDamage = 0;
//int candidateTotalBlockDamage = 0;
// int candidateTotalBlockDamage = 0;
for (Card pCard : playerCreatures) {
// if the creature can attack next turn add it to counter attackers list
// if the creature can attack next turn add it to counter attackers
// list
if (CombatUtil.canAttackNextTurn(pCard)) {
nextTurnAttackers.add(pCard);
if (pCard.getNetCombatDamage() > 0) {
candidateCounterAttackDamage += pCard.getNetCombatDamage();
//candidateTotalBlockDamage += pCard.getNetCombatDamage();
// candidateTotalBlockDamage += pCard.getNetCombatDamage();
playerForces += 1; // player forces they might use to attack
}
}
// increment player forces that are relevant to an attritional attack - includes walls
// increment player forces that are relevant to an attritional
// attack - includes walls
if (CombatUtil.canBlock(pCard)) {
playerForcesForAttritionalAttack += 1;
}
@@ -408,7 +462,8 @@ public class ComputerUtil_Attack2 {
CardList candidateAttackers = new CardList();
int candidateUnblockedDamage = 0;
for (Card pCard : computerList) {
// if the creature can attack then it's a potential attacker this turn, assume summoning sickness creatures will be able to
// if the creature can attack then it's a potential attacker this
// turn, assume summoning sickness creatures will be able to
if (CombatUtil.canAttackNextTurn(pCard)) {
candidateAttackers.add(pCard);
@@ -422,24 +477,36 @@ public class ComputerUtil_Attack2 {
// find the potential damage ratio the AI can cause
double playerLifeToDamageRatio = 1000000;
if (candidateUnblockedDamage > 0)
if (candidateUnblockedDamage > 0) {
playerLifeToDamageRatio = (double) AllZone.getHumanPlayer().life / candidateUnblockedDamage;
}
/*System.out.println(String.valueOf(aiLifeToPlayerDamageRatio) + " = ai life to player damage ratio");
System.out.println(String.valueOf(playerLifeToDamageRatio) + " = player life ai player damage ratio");*/
/*
* System.out.println(String.valueOf(aiLifeToPlayerDamageRatio) +
* " = ai life to player damage ratio");
* System.out.println(String.valueOf(playerLifeToDamageRatio) +
* " = player life ai player damage ratio");
*/
// determine if the ai outnumbers the player
int outNumber = computerForces - playerForces;
// compare the ratios, higher = better for ai
double ratioDiff = aiLifeToPlayerDamageRatio - playerLifeToDamageRatio;
/* System.out.println(String.valueOf(ratioDiff) + " = ratio difference, higher = better for ai");
System.out.println(String.valueOf(outNumber) + " = outNumber, higher = better for ai"); */
/*
* System.out.println(String.valueOf(ratioDiff) +
* " = ratio difference, higher = better for ai");
* System.out.println(String.valueOf(outNumber) +
* " = outNumber, higher = better for ai");
*/
// *********************
// if outnumber and superior ratio work out whether attritional all out attacking will work
// attritional attack will expect some creatures to die but to achieve victory by sheer weight
// of numbers attacking turn after turn. It's not calculate very carefully, the accuracy
// if outnumber and superior ratio work out whether attritional all out
// attacking will work
// attritional attack will expect some creatures to die but to achieve
// victory by sheer weight
// of numbers attacking turn after turn. It's not calculate very
// carefully, the accuracy
// can probably be improved
// *********************
boolean doAttritionalAttack = false;
@@ -455,14 +522,15 @@ public class ComputerUtil_Attack2 {
// until the attackers are used up or the player would run out of life
int attackRounds = 1;
while (attritionalAttackers.size() > 0 && playerLife > 0 && attackRounds < 99) {
// sum attacker damage
// sum attacker damage
int damageThisRound = 0;
for (int y = 0; y < attritionalAttackers.size(); y++) {
damageThisRound += attritionalAttackers.getCard(y).getNetCombatDamage();
}
// remove from player life
// remove from player life
playerLife -= damageThisRound;
// shorten attacker list by the length of the blockers - assuming all blocked are killed for convenience
// shorten attacker list by the length of the blockers - assuming
// all blocked are killed for convenience
for (int z = 0; z < playerForcesForAttritionalAttack; z++) {
if (attritionalAttackers.size() > 0) {
attritionalAttackers.remove(attritionalAttackers.size() - 1);
@@ -473,7 +541,7 @@ public class ComputerUtil_Attack2 {
doAttritionalAttack = true;
}
}
//System.out.println(doAttritionalAttack + " = do attritional attack");
// System.out.println(doAttritionalAttack + " = do attritional attack");
// *********************
// end attritional attack calculation
// *********************
@@ -486,7 +554,8 @@ public class ComputerUtil_Attack2 {
boolean doUnblockableAttack = false;
for (Card attacker : attackers) {
boolean isUnblockableCreature = true;
// check blockers individually, as the bulk canBeBlocked doesn't check all circumstances
// check blockers individually, as the bulk canBeBlocked doesn't
// check all circumstances
for (Card blocker : blockers) {
if (CombatUtil.canBlock(attacker, blocker)) {
isUnblockableCreature = false;
@@ -506,22 +575,33 @@ public class ComputerUtil_Attack2 {
// end see how long until unblockable attackers will be fatal
// *****************
// decide on attack aggression based on a comparison of forces, life totals and other considerations
// some bad "magic numbers" here, TODO replace with nice descriptive variable names
if ((ratioDiff > 0 && doAttritionalAttack)) { // (playerLifeToDamageRatio <= 1 && ratioDiff >= 1 && outNumber > 0) ||
// decide on attack aggression based on a comparison of forces, life
// totals and other considerations
// some bad "magic numbers" here, TODO replace with nice descriptive
// variable names
if ((ratioDiff > 0 && doAttritionalAttack)) { // (playerLifeToDamageRatio
// <= 1 && ratioDiff >= 1
// && outNumber > 0) ||
aiAggression = 5; // attack at all costs
} else if ((playerLifeToDamageRatio < 2 && ratioDiff >= 0) || ratioDiff > 3 || (ratioDiff > 0 && outNumber > 0)) {
aiAggression = 3; // attack expecting to kill creatures or damage player.
} else if ((playerLifeToDamageRatio < 2 && ratioDiff >= 0)
|| ratioDiff > 3 || (ratioDiff > 0 && outNumber > 0)) {
aiAggression = 3; // attack expecting to kill creatures or damage
// player.
} else if (ratioDiff >= 0 || ratioDiff + outNumber >= -1) {
// at 0 ratio expect to potentially gain an advantage by attacking first
// at 0 ratio expect to potentially gain an advantage by attacking
// first
// if the ai has a slight advantage
// or the ai has a significant advantage numerically but only a slight disadvantage damage/life
aiAggression = 2; // attack expecting to destroy creatures/be unblockable
// or the ai has a significant advantage numerically but only a
// slight disadvantage damage/life
aiAggression = 2; // attack expecting to destroy creatures/be
// unblockable
} else if (ratioDiff < 0 && aiLifeToPlayerDamageRatio > 1) {
// the player is overmatched but there are a few turns before death
aiAggression = 2; // attack expecting to destroy creatures/be unblockable
aiAggression = 2; // attack expecting to destroy creatures/be
// unblockable
} else if (doUnblockableAttack || ((ratioDiff * -1) < turnsUntilDeathByUnblockable)) {
aiAggression = 1; // look for unblockable creatures that might be able to attack for a bit of
aiAggression = 1; // look for unblockable creatures that might be
// able to attack for a bit of
// fatal damage even if the player is significantly better
} else if (ratioDiff < 0) {
aiAggression = 0;
@@ -532,13 +612,15 @@ public class ComputerUtil_Attack2 {
// End of edits
// ****************
//Exalted
if (combat.getAttackers().length == 0 && (countExaltedBonus(AllZone.getComputerPlayer()) >= 3 ||
AllZoneUtil.isCardInPlay("Rafiq of the Many", AllZone.getComputerPlayer()) ||
AllZone.getComputerPlayer().getCardsIn(Zone.Battlefield, "Battlegrace Angel").size() >= 2 ||
(AllZone.getComputerPlayer().getCardsIn(Zone.Battlefield, "Finest Hour").size() >= 1) &&
AllZone.getPhase().isFirstCombat())
&& !bAssault) {
// Exalted
if (combat.getAttackers().length == 0
&& (countExaltedBonus(AllZone.getComputerPlayer()) >= 3
|| AllZoneUtil.isCardInPlay("Rafiq of the Many", AllZone.getComputerPlayer())
|| AllZone.getComputerPlayer()
.getCardsIn(Zone.Battlefield, "Battlegrace Angel").size() >= 2 || (AllZone
.getComputerPlayer().getCardsIn(Zone.Battlefield, "Finest Hour").size() >= 1)
&& AllZone.getPhase().isFirstCombat()) && !bAssault)
{
int biggest = 0;
Card att = null;
for (int i = 0; i < attackersLeft.size(); i++) {
@@ -547,19 +629,23 @@ public class ComputerUtil_Attack2 {
att = attackersLeft.get(i);
}
}
if (att != null && CombatUtil.canAttack(att, combat))
if (att != null && CombatUtil.canAttack(att, combat)) {
combat.addAttacker(att);
}
System.out.println("Exalted");
}
//do assault (all creatures attack) if the computer would win the game
//or if the computer has 4 creatures and the player has 1
// do assault (all creatures attack) if the computer would win the game
// or if the computer has 4 creatures and the player has 1
else if (bAssault) {
System.out.println("Assault");
CardListUtil.sortAttack(attackersLeft);
for (int i = 0; i < attackersLeft.size(); i++)
if (CombatUtil.canAttack(attackersLeft.get(i), combat)) combat.addAttacker(attackersLeft.get(i));
for (int i = 0; i < attackersLeft.size(); i++) {
if (CombatUtil.canAttack(attackersLeft.get(i), combat)) {
combat.addAttacker(attackersLeft.get(i));
}
}
} else {
System.out.println("Normal attack");
@@ -571,28 +657,36 @@ public class ComputerUtil_Attack2 {
for (int i = 0; i < attackersLeft.size(); i++) {
Card attacker = attackersLeft.get(i);
int totalFirstStrikeBlockPower = 0;
if (!attacker.hasFirstStrike() && !attacker.hasDoubleStrike())
totalFirstStrikeBlockPower = CombatUtil.getTotalFirstStrikeBlockPower(attacker, AllZone.getHumanPlayer());
if (!attacker.hasFirstStrike() && !attacker.hasDoubleStrike()) {
totalFirstStrikeBlockPower = CombatUtil.getTotalFirstStrikeBlockPower(attacker,
AllZone.getHumanPlayer());
}
if (shouldAttack(attacker, blockers, combat) && (totalFirstStrikeBlockPower < attacker.getKillDamage() || aiAggression == 5)
if (shouldAttack(attacker, blockers, combat)
&& (totalFirstStrikeBlockPower < attacker.getKillDamage() || aiAggression == 5)
&& CombatUtil.canAttack(attacker, combat))
{
combat.addAttacker(attacker);
}
}
}//getAttackers()
} // getAttackers()
return combat;
}//getAttackers()
} // getAttackers()
/**
* <p>countExaltedBonus.</p>
*
* @param player a {@link forge.Player} object.
* <p>
* countExaltedBonus.
* </p>
*
* @param player
* a {@link forge.Player} object.
* @return a int.
*/
public int countExaltedBonus(Player player) {
public final int countExaltedBonus(final Player player) {
CardList list = player.getCardsIn(Zone.Battlefield);
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
public boolean addCard(final Card c) {
return c.hasKeyword("Exalted");
}
});
@@ -601,92 +695,125 @@ public class ComputerUtil_Attack2 {
}
/**
* <p>getAttack.</p>
*
* @param c a {@link forge.Card} object.
* <p>
* getAttack.
* </p>
*
* @param c
* a {@link forge.Card} object.
* @return a int.
*/
public int getAttack(Card c) {
public final int getAttack(final Card c) {
int n = c.getNetCombatDamage();
if (c.hasKeyword("Double Strike"))
if (c.hasKeyword("Double Strike")) {
n *= 2;
}
return n;
}
/**
* <p>shouldAttack.</p>
*
* @param attacker a {@link forge.Card} object.
* @param defenders a {@link forge.CardList} object.
* @param combat a {@link forge.Combat} object.
* <p>
* shouldAttack.
* </p>
*
* @param attacker
* a {@link forge.Card} object.
* @param defenders
* a {@link forge.CardList} object.
* @param combat
* a {@link forge.Combat} object.
* @return a boolean.
*/
public boolean shouldAttack(Card attacker, CardList defenders, Combat combat) {
boolean canBeKilledByOne = false; // indicates if the attacker can be killed by a single blockers
boolean canKillAll = true; // indicates if the attacker can kill all single blockers
boolean canKillAllDangerous = true; // indicates if the attacker can kill all single blockers with wither or infect
public final boolean shouldAttack(final Card attacker, final CardList defenders, final Combat combat) {
boolean canBeKilledByOne = false; // indicates if the attacker can be
// killed by a single blockers
boolean canKillAll = true; // indicates if the attacker can kill all
// single blockers
boolean canKillAllDangerous = true; // indicates if the attacker can
// kill all single blockers with
// wither or infect
boolean isWorthLessThanAllKillers = true;
boolean canBeBlocked = false;
if (!isEffectiveAttacker(attacker, combat)) return false;
if (!isEffectiveAttacker(attacker, combat)) {
return false;
}
// look at the attacker in relation to the blockers to establish a number of factors about the attacking
// context that will be relevant to the attackers decision according to the selected strategy
// look at the attacker in relation to the blockers to establish a
// number of factors about the attacking
// context that will be relevant to the attackers decision according to
// the selected strategy
for (Card defender : defenders) {
if (CombatUtil.canBlock(attacker, defender)) { //, combat )) {
if (CombatUtil.canBlock(attacker, defender)) { // , combat )) {
canBeBlocked = true;
if (CombatUtil.canDestroyAttacker(attacker, defender, combat, false)) {
canBeKilledByOne = true; // there is a single creature on the battlefield that can kill the creature
// see if the defending creature is of higher or lower value. We don't want to attack only to lose value
canBeKilledByOne = true; // there is a single creature on
// the battlefield that can kill
// the creature
// see if the defending creature is of higher or lower
// value. We don't want to attack only to lose value
if (CardFactoryUtil.evaluateCreature(defender) <= CardFactoryUtil.evaluateCreature(attacker)) {
isWorthLessThanAllKillers = false;
}
}
// see if this attacking creature can destroy this defender, if not record that it can't kill everything
// see if this attacking creature can destroy this defender, if
// not record that it can't kill everything
if (!CombatUtil.canDestroyBlocker(defender, attacker, combat, false)) {
canKillAll = false;
if (defender.hasKeyword("Wither") || defender.hasKeyword("Infect")) {
canKillAllDangerous = false; // there is a dangerous creature that can survive an attack from this creature
canKillAllDangerous = false; // there is a dangerous
// creature that can
// survive an attack from
// this creature
}
}
}
}
// if the creature cannot block and can kill all opponents they might as well attack, they do nothing staying back
// if the creature cannot block and can kill all opponents they might as
// well attack, they do nothing staying back
if (canKillAll && !CombatUtil.canBlock(attacker) && isWorthLessThanAllKillers) {
System.out.println(attacker.getName() + " = attacking because they can't block, expecting to kill or damage player");
System.out.println(attacker.getName()
+ " = attacking because they can't block, expecting to kill or damage player");
return true;
}
// decide if the creature should attack based on the prevailing strategy choice in aiAggression
// decide if the creature should attack based on the prevailing strategy
// choice in aiAggression
switch (aiAggression) {
case 5: // all out attacking
System.out.println(attacker.getName() + " = all out attacking");
case 5: // all out attacking
System.out.println(attacker.getName() + " = all out attacking");
return true;
case 4: // expecting to at least trade with something
if (canKillAll || (canKillAllDangerous && !canBeKilledByOne) || !canBeBlocked) {
System.out.println(attacker.getName() + " = attacking expecting to at least trade with something");
return true;
case 4: // expecting to at least trade with something
if (canKillAll || (canKillAllDangerous && !canBeKilledByOne) || !canBeBlocked) {
System.out.println(attacker.getName() + " = attacking expecting to at least trade with something");
return true;
}
case 3: // expecting to at least kill a creature of equal value, not be blocked
if ((canKillAll && isWorthLessThanAllKillers) || (canKillAllDangerous && !canBeKilledByOne) || !canBeBlocked) {
System.out.println(attacker.getName() + " = attacking expecting to kill creature or cause damage, or is unblockable");
return true;
}
case 2: // attack expecting to attract a group block or destroying a single blocker and surviving
if ((canKillAll && !canBeKilledByOne) || !canBeBlocked) {
System.out.println(attacker.getName() + " = attacking expecting to survive or attract group block");
return true;
}
case 1: // unblockable creatures only
if (!canBeBlocked) {
System.out.println(attacker.getName() + " = attacking expecting not to be blocked");
return true;
}
}
case 3: // expecting to at least kill a creature of equal value, not be
// blocked
if ((canKillAll && isWorthLessThanAllKillers) || (canKillAllDangerous && !canBeKilledByOne)
|| !canBeBlocked) {
System.out.println(attacker.getName()
+ " = attacking expecting to kill creature or cause damage, or is unblockable");
return true;
}
case 2: // attack expecting to attract a group block or destroying a
// single blocker and surviving
if ((canKillAll && !canBeKilledByOne) || !canBeBlocked) {
System.out.println(attacker.getName() + " = attacking expecting to survive or attract group block");
return true;
}
case 1: // unblockable creatures only
if (!canBeBlocked) {
System.out.println(attacker.getName() + " = attacking expecting not to be blocked");
return true;
}
default:
break;
}
return false; // don't attack
}
}//end class ComputerUtil_Attack2
} // end class ComputerUtil_Attack2

View File

@@ -1,32 +1,44 @@
package forge;
import forge.card.cardFactory.CardFactoryUtil;
import java.util.ArrayList;
import forge.card.cardFactory.CardFactoryUtil;
/**
* <p>ComputerUtil_Block2 class.</p>
*
* <p>
* ComputerUtil_Block2 class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class ComputerUtil_Block2 {
/** Constant <code>attackers</code> */
private static CardList attackers = new CardList(); //all attackers
/** Constant <code>attackersLeft</code> */
private static CardList attackersLeft = new CardList(); //keeps track of all currently unblocked attackers
/** Constant <code>blockedButUnkilled</code> */
private static CardList blockedButUnkilled = new CardList(); //blocked attackers that currently wouldn't be destroyed
/** Constant <code>blockersLeft</code> */
private static CardList blockersLeft = new CardList(); //keeps track of all unassigned blockers
/** Constant <code>diff=0</code> */
/** Constant <code>attackers</code>. */
private static CardList attackers = new CardList(); // all attackers
/** Constant <code>attackersLeft</code>. */
private static CardList attackersLeft = new CardList(); // keeps track of
// all currently
// unblocked
// attackers
/** Constant <code>blockedButUnkilled</code>. */
private static CardList blockedButUnkilled = new CardList(); // blocked
// attackers
// that
// currently
// wouldn't be
// destroyed
/** Constant <code>blockersLeft</code>. */
private static CardList blockersLeft = new CardList(); // keeps track of all
// unassigned
// blockers
/** Constant <code>diff=0</code>. */
private static int diff = 0;
/**
* <p>Getter for the field <code>attackers</code>.</p>
*
* <p>
* Getter for the field <code>attackers</code>.
* </p>
*
* @return a {@link forge.CardList} object.
*/
private static CardList getAttackers() {
@@ -34,17 +46,22 @@ public class ComputerUtil_Block2 {
}
/**
* <p>Setter for the field <code>attackers</code>.</p>
*
* @param cardList a {@link forge.CardList} object.
* <p>
* Setter for the field <code>attackers</code>.
* </p>
*
* @param cardList
* a {@link forge.CardList} object.
*/
private static void setAttackers(CardList cardList) {
private static void setAttackers(final CardList cardList) {
attackers = (cardList);
}
/**
* <p>Getter for the field <code>attackersLeft</code>.</p>
*
* <p>
* Getter for the field <code>attackersLeft</code>.
* </p>
*
* @return a {@link forge.CardList} object.
*/
private static CardList getAttackersLeft() {
@@ -52,17 +69,22 @@ public class ComputerUtil_Block2 {
}
/**
* <p>Setter for the field <code>attackersLeft</code>.</p>
*
* @param cardList a {@link forge.CardList} object.
* <p>
* Setter for the field <code>attackersLeft</code>.
* </p>
*
* @param cardList
* a {@link forge.CardList} object.
*/
private static void setAttackersLeft(CardList cardList) {
private static void setAttackersLeft(final CardList cardList) {
attackersLeft = (cardList);
}
/**
* <p>Getter for the field <code>blockedButUnkilled</code>.</p>
*
* <p>
* Getter for the field <code>blockedButUnkilled</code>.
* </p>
*
* @return a {@link forge.CardList} object.
*/
private static CardList getBlockedButUnkilled() {
@@ -71,17 +93,22 @@ public class ComputerUtil_Block2 {
}
/**
* <p>Setter for the field <code>blockedButUnkilled</code>.</p>
*
* @param cardList a {@link forge.CardList} object.
* <p>
* Setter for the field <code>blockedButUnkilled</code>.
* </p>
*
* @param cardList
* a {@link forge.CardList} object.
*/
private static void setBlockedButUnkilled(CardList cardList) {
private static void setBlockedButUnkilled(final CardList cardList) {
blockedButUnkilled = (cardList);
}
/**
* <p>Getter for the field <code>blockersLeft</code>.</p>
*
* <p>
* Getter for the field <code>blockersLeft</code>.
* </p>
*
* @return a {@link forge.CardList} object.
*/
private static CardList getBlockersLeft() {
@@ -89,17 +116,22 @@ public class ComputerUtil_Block2 {
}
/**
* <p>Setter for the field <code>blockersLeft</code>.</p>
*
* @param cardList a {@link forge.CardList} object.
* <p>
* Setter for the field <code>blockersLeft</code>.
* </p>
*
* @param cardList
* a {@link forge.CardList} object.
*/
private static void setBlockersLeft(CardList cardList) {
private static void setBlockersLeft(final CardList cardList) {
blockersLeft = (cardList);
}
/**
* <p>Getter for the field <code>diff</code>.</p>
*
* <p>
* Getter for the field <code>diff</code>.
* </p>
*
* @return a int.
*/
private static int getDiff() {
@@ -107,129 +139,166 @@ public class ComputerUtil_Block2 {
}
/**
* <p>Setter for the field <code>diff</code>.</p>
*
* @param diff a int.
* <p>
* Setter for the field <code>diff</code>.
* </p>
*
* @param diff
* a int.
*/
private static void setDiff(int diff) {
private static void setDiff(final int diff) {
ComputerUtil_Block2.diff = (diff);
}
//finds the creatures able to block the attacker
// finds the creatures able to block the attacker
/**
* <p>getPossibleBlockers.</p>
*
* @param attacker a {@link forge.Card} object.
* @param blockersLeft a {@link forge.CardList} object.
* @param combat a {@link forge.Combat} object.
* <p>
* getPossibleBlockers.
* </p>
*
* @param attacker
* a {@link forge.Card} object.
* @param blockersLeft
* a {@link forge.CardList} object.
* @param combat
* a {@link forge.Combat} object.
* @return a {@link forge.CardList} object.
*/
private static CardList getPossibleBlockers(Card attacker, CardList blockersLeft, Combat combat) {
private static CardList getPossibleBlockers(final Card attacker, final CardList blockersLeft, Combat combat) {
CardList blockers = new CardList();
for (Card blocker : blockersLeft) {
//if the blocker can block a creature with lure it can't block a creature without
if (CombatUtil.canBlock(attacker, blocker, combat)) blockers.add(blocker);
// if the blocker can block a creature with lure it can't block a
// creature without
if (CombatUtil.canBlock(attacker, blocker, combat)) {
blockers.add(blocker);
}
}
return blockers;
}
//finds blockers that won't be destroyed
// finds blockers that won't be destroyed
/**
* <p>getSafeBlockers.</p>
*
* @param attacker a {@link forge.Card} object.
* @param blockersLeft a {@link forge.CardList} object.
* @param combat a {@link forge.Combat} object.
* <p>
* getSafeBlockers.
* </p>
*
* @param attacker
* a {@link forge.Card} object.
* @param blockersLeft
* a {@link forge.CardList} object.
* @param combat
* a {@link forge.Combat} object.
* @return a {@link forge.CardList} object.
*/
private static CardList getSafeBlockers(Card attacker, CardList blockersLeft, Combat combat) {
private static CardList getSafeBlockers(final Card attacker, final CardList blockersLeft, Combat combat) {
CardList blockers = new CardList();
for (Card b : blockersLeft) {
if (!CombatUtil.canDestroyBlocker(b, attacker, combat, false)) blockers.add(b);
if (!CombatUtil.canDestroyBlocker(b, attacker, combat, false)) {
blockers.add(b);
}
}
return blockers;
}
//finds blockers that destroy the attacker
// finds blockers that destroy the attacker
/**
* <p>getKillingBlockers.</p>
*
* @param attacker a {@link forge.Card} object.
* @param blockersLeft a {@link forge.CardList} object.
* @param combat a {@link forge.Combat} object.
* <p>
* getKillingBlockers.
* </p>
*
* @param attacker
* a {@link forge.Card} object.
* @param blockersLeft
* a {@link forge.CardList} object.
* @param combat
* a {@link forge.Combat} object.
* @return a {@link forge.CardList} object.
*/
private static CardList getKillingBlockers(Card attacker, CardList blockersLeft, Combat combat) {
private static CardList getKillingBlockers(final Card attacker, final CardList blockersLeft, Combat combat) {
CardList blockers = new CardList();
for (Card b : blockersLeft) {
if (CombatUtil.canDestroyAttacker(attacker, b, combat, false)) blockers.add(b);
if (CombatUtil.canDestroyAttacker(attacker, b, combat, false)) {
blockers.add(b);
}
}
return blockers;
}
/**
* <p>sortPotentialAttackers.</p>
*
* @param combat a {@link forge.Combat} object.
* <p>
* sortPotentialAttackers.
* </p>
*
* @param combat
* a {@link forge.Combat} object.
* @return a {@link forge.CardList} object.
*/
public static CardList sortPotentialAttackers(Combat combat) {
public static CardList sortPotentialAttackers(final Combat combat) {
CardList[] attackerLists = combat.sortAttackerByDefender();
CardList sortedAttackers = new CardList();
ArrayList<Object> defenders = combat.getDefenders();
//Begin with the attackers that pose the biggest threat
// Begin with the attackers that pose the biggest threat
CardListUtil.sortByEvaluateCreature(attackerLists[0]);
CardListUtil.sortAttack(attackerLists[0]);
// If I don't have any planeswalkers than sorting doesn't really matter
if (defenders.size() == 1)
if (defenders.size() == 1) {
return attackerLists[0];
}
boolean bLifeInDanger = CombatUtil.lifeInDanger(combat);
// TODO: Add creatures attacking Planeswalkers in order of which we want to protect
// defend planeswalkers with more loyalty before planeswalkers with less loyalty
// TODO Add creatures attacking Planeswalkers in order of which we want
// to protect
// defend planeswalkers with more loyalty before planeswalkers with less
// loyalty
// if planeswalker will be too difficult to defend don't even bother
for (int i = 1; i < attackerLists.length; i++) {
//Begin with the attackers that pose the biggest threat
// Begin with the attackers that pose the biggest threat
CardListUtil.sortAttack(attackerLists[i]);
for (Card c : attackerLists[i])
for (Card c : attackerLists[i]) {
sortedAttackers.add(c);
}
}
if (bLifeInDanger) {
// add creatures attacking the Player to the front of the list
for (Card c : attackerLists[0])
for (Card c : attackerLists[0]) {
sortedAttackers.add(0, c);
}
} else {
// add creatures attacking the Player to the back of the list
for (Card c : attackerLists[0])
for (Card c : attackerLists[0]) {
sortedAttackers.add(c);
}
}
return sortedAttackers;
}
// ======================= block assignment functions ================================
// ======================= block assignment functions
// ================================
// Good Blocks means a good trade or no trade
/**
* <p>makeGoodBlocks.</p>
*
* @param combat a {@link forge.Combat} object.
* <p>
* makeGoodBlocks.
* </p>
*
* @param combat
* a {@link forge.Combat} object.
* @return a {@link forge.Combat} object.
*/
private static Combat makeGoodBlocks(Combat combat) {
private static Combat makeGoodBlocks(final Combat combat) {
CardList currentAttackers = new CardList(getAttackersLeft().toArray());
@@ -243,12 +312,12 @@ public class ComputerUtil_Block2 {
CardList killingBlockers;
if (safeBlockers.size() > 0) {
// 1.Blockers that can destroy the attacker but won't get destroyed
// 1.Blockers that can destroy the attacker but won't get
// destroyed
killingBlockers = getKillingBlockers(attacker, safeBlockers, combat);
if (killingBlockers.size() > 0) blocker = CardFactoryUtil.AI_getWorstCreature(killingBlockers);
// 2.Blockers that won't get destroyed
else {
if (killingBlockers.size() > 0) {
blocker = CardFactoryUtil.AI_getWorstCreature(killingBlockers);
} else {
blocker = CardFactoryUtil.AI_getWorstCreature(safeBlockers);
getBlockedButUnkilled().add(attacker);
}
@@ -256,10 +325,13 @@ public class ComputerUtil_Block2 {
else {
killingBlockers = getKillingBlockers(attacker, blockers, combat);
if (killingBlockers.size() > 0) {
// 3.Blockers that can destroy the attacker and are worth less
// 3.Blockers that can destroy the attacker and are worth
// less
Card worst = CardFactoryUtil.AI_getWorstCreature(killingBlockers);
if (CardFactoryUtil.evaluateCreature(worst) + getDiff() < CardFactoryUtil.evaluateCreature(attacker)) {
if (CardFactoryUtil.evaluateCreature(worst) + getDiff() < CardFactoryUtil
.evaluateCreature(attacker))
{
blocker = worst;
}
}
@@ -276,34 +348,43 @@ public class ComputerUtil_Block2 {
// Good Gang Blocks means a good trade or no trade
/**
* <p>makeGangBlocks.</p>
*
* @param combat a {@link forge.Combat} object.
* <p>
* makeGangBlocks.
* </p>
*
* @param combat
* a {@link forge.Combat} object.
* @return a {@link forge.Combat} object.
*/
private static Combat makeGangBlocks(Combat combat) {
private static Combat makeGangBlocks(final Combat combat) {
CardList currentAttackers = new CardList(getAttackersLeft().toArray());
currentAttackers = currentAttackers.getKeywordsDontContain("Rampage");
currentAttackers = currentAttackers.getKeywordsDontContain("CARDNAME can't be blocked by more than one creature.");
currentAttackers = currentAttackers
.getKeywordsDontContain("CARDNAME can't be blocked by more than one creature.");
CardList blockers;
//Try to block an attacker without first strike with a gang of first strikers
// Try to block an attacker without first strike with a gang of first
// strikers
for (Card attacker : getAttackersLeft()) {
if (!attacker.hasKeyword("First Strike")
&& !attacker.hasKeyword("Double Strike")) {
if (!attacker.hasKeyword("First Strike") && !attacker.hasKeyword("Double Strike")) {
blockers = getPossibleBlockers(attacker, getBlockersLeft(), combat);
CardList firstStrikeBlockers = new CardList();
CardList blockGang = new CardList();
for (int i = 0; i < blockers.size(); i++)
if (blockers.get(i).hasFirstStrike() || blockers.get(i).hasDoubleStrike())
for (int i = 0; i < blockers.size(); i++) {
if (blockers.get(i).hasFirstStrike() || blockers.get(i).hasDoubleStrike()) {
firstStrikeBlockers.add(blockers.get(i));
}
}
if (firstStrikeBlockers.size() > 1) {
CardListUtil.sortAttack(firstStrikeBlockers);
for (Card blocker : firstStrikeBlockers) {
int damageNeeded = attacker.getKillDamage() + CombatUtil.predictToughnessBonusOfAttacker(attacker, blocker, combat);
//if the total damage of the blockgang was not enough without but is enough with this blocker finish the blockgang
int damageNeeded = attacker.getKillDamage()
+ CombatUtil.predictToughnessBonusOfAttacker(attacker, blocker, combat);
// if the total damage of the blockgang was not enough
// without but is enough with this blocker finish the
// blockgang
if (CombatUtil.totalDamageOfBlockers(attacker, blockGang) < damageNeeded) {
blockGang.add(blocker);
if (CombatUtil.totalDamageOfBlockers(attacker, blockGang) >= damageNeeded) {
@@ -322,26 +403,32 @@ public class ComputerUtil_Block2 {
setAttackersLeft(new CardList(currentAttackers.toArray()));
currentAttackers = new CardList(getAttackersLeft().toArray());
//Try to block an attacker with two blockers of which only one will die
// Try to block an attacker with two blockers of which only one will die
for (final Card attacker : getAttackersLeft()) {
blockers = getPossibleBlockers(attacker, getBlockersLeft(), combat);
CardList usableBlockers;
CardList blockGang = new CardList();
int absorbedDamage = 0; //The amount of damage needed to kill the first blocker
int currentValue = 0; //The value of the creatures in the blockgang
int absorbedDamage = 0; // The amount of damage needed to kill the
// first blocker
int currentValue = 0; // The value of the creatures in the blockgang
//Try to add blockers that could be destroyed, but are worth less than the attacker
//Don't use blockers without First Strike or Double Strike if attacker has it
// Try to add blockers that could be destroyed, but are worth less
// than the attacker
// Don't use blockers without First Strike or Double Strike if
// attacker has it
usableBlockers = blockers.filter(new CardListFilter() {
public boolean addCard(Card c) {
public boolean addCard(final Card c) {
if ((attacker.hasKeyword("First Strike") || attacker.hasKeyword("Double Strike"))
&& !(c.hasKeyword("First Strike") || c.hasKeyword("Double Strike")))
{
return false;
}
return CardFactoryUtil.evaluateCreature(c) + getDiff() < CardFactoryUtil.evaluateCreature(attacker);
}
});
if (usableBlockers.size() < 2)
if (usableBlockers.size() < 2) {
return combat;
}
Card leader = CardFactoryUtil.AI_getBestCreature(usableBlockers);
blockGang.add(leader);
@@ -350,17 +437,23 @@ public class ComputerUtil_Block2 {
currentValue = CardFactoryUtil.evaluateCreature(leader);
for (Card blocker : usableBlockers) {
//Add an additional blocker if the current blockers are not enough and the new one would deal the remaining damage
// Add an additional blocker if the current blockers are not
// enough and the new one would deal the remaining damage
int currentDamage = CombatUtil.totalDamageOfBlockers(attacker, blockGang);
int additionalDamage = CombatUtil.dealsDamageAsBlocker(attacker, blocker);
int absorbedDamage2 = blocker.getEnoughDamageToKill(attacker.getNetCombatDamage(), attacker, true);
int addedValue = CardFactoryUtil.evaluateCreature(blocker);
int damageNeeded = attacker.getKillDamage() + CombatUtil.predictToughnessBonusOfAttacker(attacker, blocker, combat);
if (damageNeeded > currentDamage
&& !(damageNeeded > currentDamage + additionalDamage) //The attacker will be killed
&& (absorbedDamage2 + absorbedDamage > attacker.getNetCombatDamage() //only one blocker can be killed
|| currentValue + addedValue - 50 <= CardFactoryUtil.evaluateCreature(attacker)) //attacker is worth more
&& CombatUtil.canBlock(attacker, blocker, combat)) {//this is needed for attackers that can't be blocked by more than 1
int damageNeeded = attacker.getKillDamage()
+ CombatUtil.predictToughnessBonusOfAttacker(attacker, blocker, combat);
if (damageNeeded > currentDamage && !(damageNeeded > currentDamage + additionalDamage)
// The attacker will be killed
&& (absorbedDamage2 + absorbedDamage > attacker.getNetCombatDamage()
// only one blocker can be killed
|| currentValue + addedValue - 50 <= CardFactoryUtil.evaluateCreature(attacker))
// attacker is worth more
&& CombatUtil.canBlock(attacker, blocker, combat))
{
// this is needed for attackers that can't be blocked by more than 1
currentAttackers.remove(attacker);
combat.addBlocker(attacker, blocker);
combat.addBlocker(attacker, leader);
@@ -377,19 +470,22 @@ public class ComputerUtil_Block2 {
// Bad Trade Blocks (should only be made if life is in danger)
/**
* <p>makeTradeBlocks.</p>
*
* @param combat a {@link forge.Combat} object.
* <p>
* makeTradeBlocks.
* </p>
*
* @param combat
* a {@link forge.Combat} object.
* @return a {@link forge.Combat} object.
*/
private static Combat makeTradeBlocks(Combat combat) {
private static Combat makeTradeBlocks(final Combat combat) {
CardList currentAttackers = new CardList(getAttackersLeft().toArray());
CardList killingBlockers;
for (Card attacker : getAttackersLeft()) {
killingBlockers =
getKillingBlockers(attacker, getPossibleBlockers(attacker, getBlockersLeft(), combat), combat);
killingBlockers = getKillingBlockers(attacker, getPossibleBlockers(attacker, getBlockersLeft(), combat),
combat);
if (killingBlockers.size() > 0 && CombatUtil.lifeInDanger(combat)) {
Card blocker = CardFactoryUtil.AI_getWorstCreature(killingBlockers);
combat.addBlocker(attacker, blocker);
@@ -403,12 +499,15 @@ public class ComputerUtil_Block2 {
// Chump Blocks (should only be made if life is in danger)
/**
* <p>makeChumpBlocks.</p>
*
* @param combat a {@link forge.Combat} object.
* <p>
* makeChumpBlocks.
* </p>
*
* @param combat
* a {@link forge.Combat} object.
* @return a {@link forge.Combat} object.
*/
private static Combat makeChumpBlocks(Combat combat) {
private static Combat makeChumpBlocks(final Combat combat) {
CardList currentAttackers = new CardList(getAttackersLeft().toArray());
CardList chumpBlockers;
@@ -427,30 +526,42 @@ public class ComputerUtil_Block2 {
return combat;
}
//Reinforce blockers blocking attackers with trample (should only be made if life is in danger)
// Reinforce blockers blocking attackers with trample (should only be made
// if life is in danger)
/**
* <p>reinforceBlockersAgainstTrample.</p>
*
* @param combat a {@link forge.Combat} object.
* <p>
* reinforceBlockersAgainstTrample.
* </p>
*
* @param combat
* a {@link forge.Combat} object.
* @return a {@link forge.Combat} object.
*/
private static Combat reinforceBlockersAgainstTrample(Combat combat) {
private static Combat reinforceBlockersAgainstTrample(final Combat combat) {
CardList chumpBlockers;
CardList tramplingAttackers = getAttackers().getKeyword("Trample");
tramplingAttackers = tramplingAttackers.getKeywordsDontContain("Rampage"); //Don't make it worse
tramplingAttackers = tramplingAttackers.getKeywordsDontContain("CARDNAME can't be blocked by more than one creature.");
//TODO - should check here for a "rampage-like" trigger that replaced the keyword:
tramplingAttackers = tramplingAttackers.getKeywordsDontContain("Rampage"); // Don't
// make
// it
// worse
tramplingAttackers = tramplingAttackers
.getKeywordsDontContain("CARDNAME can't be blocked by more than one creature.");
// TODO - should check here for a "rampage-like" trigger that replaced
// the keyword:
// "Whenever CARDNAME becomes blocked, it gets +1/+1 until end of turn for each creature blocking it."
for (Card attacker : tramplingAttackers) {
chumpBlockers = getPossibleBlockers(attacker, getBlockersLeft(), combat);
for (Card blocker : chumpBlockers) {
//Add an additional blocker if the current blockers are not enough and the new one would suck some of the damage
if (CombatUtil.getAttack(attacker) > CombatUtil.totalShieldDamage(attacker, combat.getBlockers(attacker))
&& CombatUtil.shieldDamage(attacker, blocker) > 0 && CombatUtil.canBlock(attacker, blocker, combat)
&& CombatUtil.lifeInDanger(combat)) {
// Add an additional blocker if the current blockers are not
// enough and the new one would suck some of the damage
if (CombatUtil.getAttack(attacker) > CombatUtil.totalShieldDamage(attacker,
combat.getBlockers(attacker))
&& CombatUtil.shieldDamage(attacker, blocker) > 0
&& CombatUtil.canBlock(attacker, blocker, combat) && CombatUtil.lifeInDanger(combat))
{
combat.addBlocker(attacker, blocker);
getBlockersLeft().remove(blocker);
}
@@ -460,54 +571,74 @@ public class ComputerUtil_Block2 {
return combat;
}
//Support blockers not destroying the attacker with more blockers to try to kill the attacker
// Support blockers not destroying the attacker with more blockers to try to
// kill the attacker
/**
* <p>reinforceBlockersToKill.</p>
*
* @param combat a {@link forge.Combat} object.
* <p>
* reinforceBlockersToKill.
* </p>
*
* @param combat
* a {@link forge.Combat} object.
* @return a {@link forge.Combat} object.
*/
private static Combat reinforceBlockersToKill(Combat combat) {
private static Combat reinforceBlockersToKill(final Combat combat) {
CardList safeBlockers;
CardList blockers;
CardList targetAttackers = getBlockedButUnkilled().getKeywordsDontContain("Rampage"); //Don't make it worse
targetAttackers = targetAttackers.getKeywordsDontContain("CARDNAME can't be blocked by more than one creature.");
//TODO - should check here for a "rampage-like" trigger that replaced the keyword:
CardList targetAttackers = getBlockedButUnkilled().getKeywordsDontContain("Rampage"); // Don't
// make
// it
// worse
targetAttackers = targetAttackers
.getKeywordsDontContain("CARDNAME can't be blocked by more than one creature.");
// TODO - should check here for a "rampage-like" trigger that replaced
// the keyword:
// "Whenever CARDNAME becomes blocked, it gets +1/+1 until end of turn for each creature blocking it."
for (Card attacker : targetAttackers) {
blockers = getPossibleBlockers(attacker, getBlockersLeft(), combat);
//Try to use safe blockers first
// Try to use safe blockers first
safeBlockers = getSafeBlockers(attacker, blockers, combat);
for (Card blocker : safeBlockers) {
int damageNeeded = attacker.getKillDamage() + CombatUtil.predictToughnessBonusOfAttacker(attacker, blocker, combat);
//Add an additional blocker if the current blockers are not enough and the new one would deal additional damage
int damageNeeded = attacker.getKillDamage()
+ CombatUtil.predictToughnessBonusOfAttacker(attacker, blocker, combat);
// Add an additional blocker if the current blockers are not
// enough and the new one would deal additional damage
if (damageNeeded > CombatUtil.totalDamageOfBlockers(attacker, combat.getBlockers(attacker))
&& CombatUtil.dealsDamageAsBlocker(attacker, blocker) > 0 && CombatUtil.canBlock(attacker, blocker, combat)) {
&& CombatUtil.dealsDamageAsBlocker(attacker, blocker) > 0
&& CombatUtil.canBlock(attacker, blocker, combat))
{
combat.addBlocker(attacker, blocker);
getBlockersLeft().remove(blocker);
}
blockers.remove(blocker); //Don't check them again next
blockers.remove(blocker); // Don't check them again next
}
//Try to add blockers that could be destroyed, but are worth less than the attacker
//Don't use blockers without First Strike or Double Strike if attacker has it
// Try to add blockers that could be destroyed, but are worth less
// than the attacker
// Don't use blockers without First Strike or Double Strike if
// attacker has it
if (attacker.hasKeyword("First Strike") || attacker.hasKeyword("Double Strike")) {
safeBlockers = blockers.getKeyword("First Strike");
safeBlockers.addAll(blockers.getKeyword("Double Strike"));
} else safeBlockers = new CardList(blockers.toArray());
} else {
safeBlockers = new CardList(blockers.toArray());
}
for (Card blocker : safeBlockers) {
int damageNeeded = attacker.getKillDamage() + CombatUtil.predictToughnessBonusOfAttacker(attacker, blocker, combat);
//Add an additional blocker if the current blockers are not enough and the new one would deal the remaining damage
int damageNeeded = attacker.getKillDamage()
+ CombatUtil.predictToughnessBonusOfAttacker(attacker, blocker, combat);
// Add an additional blocker if the current blockers are not
// enough and the new one would deal the remaining damage
int currentDamage = CombatUtil.totalDamageOfBlockers(attacker, combat.getBlockers(attacker));
int additionalDamage = CombatUtil.dealsDamageAsBlocker(attacker, blocker);
if (damageNeeded > currentDamage
&& !(damageNeeded > currentDamage + additionalDamage)
&& CardFactoryUtil.evaluateCreature(blocker) + getDiff() < CardFactoryUtil.evaluateCreature(attacker)
&& CombatUtil.canBlock(attacker, blocker, combat)) {
&& CardFactoryUtil.evaluateCreature(blocker) + getDiff() < CardFactoryUtil
.evaluateCreature(attacker) && CombatUtil.canBlock(attacker, blocker, combat))
{
combat.addBlocker(attacker, blocker);
getBlockersLeft().removeAll(blocker);
}
@@ -518,50 +649,83 @@ public class ComputerUtil_Block2 {
}
/**
* <p>resetBlockers.</p>
*
* @param combat a {@link forge.Combat} object.
* @param possibleBlockers a {@link forge.CardList} object.
* <p>
* resetBlockers.
* </p>
*
* @param combat
* a {@link forge.Combat} object.
* @param possibleBlockers
* a {@link forge.CardList} object.
* @return a {@link forge.Combat} object.
*/
private static Combat resetBlockers(Combat combat, CardList possibleBlockers) {
private static Combat resetBlockers(final Combat combat, final CardList possibleBlockers) {
CardList oldBlockers = combat.getAllBlockers();
for (Card blocker : oldBlockers) {
combat.removeFromCombat(blocker);
}
setAttackersLeft(new CardList(getAttackers().toArray())); //keeps track of all currently unblocked attackers
setBlockersLeft(new CardList(possibleBlockers.toArray())); //keeps track of all unassigned blockers
setBlockedButUnkilled(new CardList()); //keeps track of all blocked attackers that currently wouldn't be destroyed
setAttackersLeft(new CardList(getAttackers().toArray())); // keeps track
// of all
// currently
// unblocked
// attackers
setBlockersLeft(new CardList(possibleBlockers.toArray())); // keeps
// track of
// all
// unassigned
// blockers
setBlockedButUnkilled(new CardList()); // keeps track of all blocked
// attackers that currently
// wouldn't be destroyed
return combat;
}
//Main function
// Main function
/**
* <p>getBlockers.</p>
*
* @param originalCombat a {@link forge.Combat} object.
* @param possibleBlockers a {@link forge.CardList} object.
* <p>
* getBlockers.
* </p>
*
* @param originalCombat
* a {@link forge.Combat} object.
* @param possibleBlockers
* a {@link forge.CardList} object.
* @return a {@link forge.Combat} object.
*/
static public Combat getBlockers(Combat originalCombat, CardList possibleBlockers) {
public static Combat getBlockers(final Combat originalCombat, final CardList possibleBlockers) {
Combat combat = originalCombat;
setAttackers(sortPotentialAttackers(combat));
if (getAttackers().size() == 0)
if (getAttackers().size() == 0) {
return combat;
}
setAttackersLeft(new CardList(getAttackers().toArray())); //keeps track of all currently unblocked attackers
setBlockersLeft(new CardList(possibleBlockers.toArray())); //keeps track of all unassigned blockers
setBlockedButUnkilled(new CardList()); //keeps track of all blocked attackers that currently wouldn't be destroyed
setAttackersLeft(new CardList(getAttackers().toArray())); // keeps track
// of all
// currently
// unblocked
// attackers
setBlockersLeft(new CardList(possibleBlockers.toArray())); // keeps
// track of
// all
// unassigned
// blockers
setBlockedButUnkilled(new CardList()); // keeps track of all blocked
// attackers that currently
// wouldn't be destroyed
CardList blockers;
CardList chumpBlockers;
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
// remove all attackers that can't be blocked anyway
for (Card a : getAttackers()) {
@@ -572,52 +736,85 @@ public class ComputerUtil_Block2 {
// remove all blockers that can't block anyway
for (Card b : possibleBlockers) {
if (!CombatUtil.canBlock(b, combat)) getBlockersLeft().remove(b);
if (!CombatUtil.canBlock(b, combat)) {
getBlockersLeft().remove(b);
}
}
if (getAttackersLeft().size() == 0)
if (getAttackersLeft().size() == 0) {
return combat;
}
//Begin with the weakest blockers
// Begin with the weakest blockers
CardListUtil.sortAttackLowFirst(getBlockersLeft());
//== 1. choose best blocks first ==
// == 1. choose best blocks first ==
combat = makeGoodBlocks(combat);
combat = makeGangBlocks(combat);
if (CombatUtil.lifeInDanger(combat))
combat = makeTradeBlocks(combat); //choose necessary trade blocks if life is in danger
if (CombatUtil.lifeInDanger(combat))
combat = makeChumpBlocks(combat); //choose necessary chump blocks if life is still in danger
//Reinforce blockers blocking attackers with trample if life is still in danger
if (CombatUtil.lifeInDanger(combat)) combat = reinforceBlockersAgainstTrample(combat);
//Support blockers not destroying the attacker with more blockers to try to kill the attacker
if (!CombatUtil.lifeInDanger(combat)) combat = reinforceBlockersToKill(combat);
//== 2. If the AI life would still be in danger make a safer approach ==
if (CombatUtil.lifeInDanger(combat)) {
combat = resetBlockers(combat, possibleBlockers); // reset every block assignment
combat = makeTradeBlocks(combat); //choose necessary trade blocks if life is in danger
combat = makeTradeBlocks(combat); // choose necessary trade blocks
}
// if life is in danger
if (CombatUtil.lifeInDanger(combat)) {
combat = makeChumpBlocks(combat); // choose necessary chump blocks
}
// if life is still in danger
// Reinforce blockers blocking attackers with trample if life is still
// in danger
if (CombatUtil.lifeInDanger(combat)) {
combat = reinforceBlockersAgainstTrample(combat);
}
// Support blockers not destroying the attacker with more blockers to
// try to kill the attacker
if (!CombatUtil.lifeInDanger(combat)) {
combat = reinforceBlockersToKill(combat);
}
// == 2. If the AI life would still be in danger make a safer approach
// ==
if (CombatUtil.lifeInDanger(combat)) {
combat = resetBlockers(combat, possibleBlockers); // reset every
// block
// assignment
combat = makeTradeBlocks(combat); // choose necessary trade blocks
// if life is in danger
combat = makeGoodBlocks(combat);
if (CombatUtil.lifeInDanger(combat))
combat = makeChumpBlocks(combat); //choose necessary chump blocks if life is still in danger
//Reinforce blockers blocking attackers with trample if life is still in danger
if (CombatUtil.lifeInDanger(combat)) combat = reinforceBlockersAgainstTrample(combat);
if (CombatUtil.lifeInDanger(combat)) {
combat = makeChumpBlocks(combat); // choose necessary chump
}
// blocks if life is still in
// danger
// Reinforce blockers blocking attackers with trample if life is
// still in danger
if (CombatUtil.lifeInDanger(combat)) {
combat = reinforceBlockersAgainstTrample(combat);
}
combat = makeGangBlocks(combat);
combat = reinforceBlockersToKill(combat);
}
//== 3. If the AI life would be in serious danger make an even safer approach ==
// == 3. If the AI life would be in serious danger make an even safer
// approach ==
if (CombatUtil.lifeInSeriousDanger(combat)) {
combat = resetBlockers(combat, possibleBlockers); // reset every block assignment
combat = makeChumpBlocks(combat); //choose chump blocks
if (CombatUtil.lifeInDanger(combat))
combat = makeTradeBlocks(combat); //choose necessary trade blocks if life is in danger
if (!CombatUtil.lifeInDanger(combat)) combat = makeGoodBlocks(combat);
//Reinforce blockers blocking attackers with trample if life is still in danger
if (CombatUtil.lifeInDanger(combat)) combat = reinforceBlockersAgainstTrample(combat);
combat = resetBlockers(combat, possibleBlockers); // reset every
// block
// assignment
combat = makeChumpBlocks(combat); // choose chump blocks
if (CombatUtil.lifeInDanger(combat)) {
combat = makeTradeBlocks(combat); // choose necessary trade
}
// blocks if life is in danger
if (!CombatUtil.lifeInDanger(combat)) {
combat = makeGoodBlocks(combat);
}
// Reinforce blockers blocking attackers with trample if life is
// still in danger
if (CombatUtil.lifeInDanger(combat)) {
combat = reinforceBlockersAgainstTrample(combat);
}
combat = makeGangBlocks(combat);
//Support blockers not destroying the attacker with more blockers to try to kill the attacker
// Support blockers not destroying the attacker with more blockers
// to try to kill the attacker
combat = reinforceBlockersToKill(combat);
}
@@ -625,7 +822,9 @@ public class ComputerUtil_Block2 {
chumpBlockers = getBlockersLeft().getKeyword("CARDNAME blocks each turn if able.");
// if an attacker with lure attacks - all that can block
for (Card blocker : getBlockersLeft()) {
if (CombatUtil.mustBlockAnAttacker(blocker, combat)) chumpBlockers.add(blocker);
if (CombatUtil.mustBlockAnAttacker(blocker, combat)) {
chumpBlockers.add(blocker);
}
}
if (!chumpBlockers.isEmpty()) {
getAttackers().shuffle();

View File

@@ -1,163 +1,333 @@
package forge;
import java.util.ArrayList;
import java.util.List;
import forge.deck.Deck;
import forge.game.GameType;
/**
* <p>Constant interface.</p>
*
* <p>
* Constant interface.
* </p>
*
* @author Forge
* @version $Id$
*/
public interface Constant {
/** Constant <code>ProgramName="Forge - http://cardforge.org"</code> */
public static final String ProgramName = "Forge - http://cardforge.org";
String ProgramName = "Forge - http://cardforge.org";
//used to pass information between the GUI screens
// used to pass information between the GUI screens
/**
* The Class Runtime.
*/
public abstract class Runtime {
/** The Constant HumanDeck. */
public static final Deck[] HumanDeck = new Deck[1];
/** The Constant ComputerDeck. */
public static final Deck[] ComputerDeck = new Deck[1];
/** The game type. */
public static GameType gameType = GameType.Constructed;
/** The Constant Smooth. */
public static final boolean[] Smooth = new boolean[1];
/** The Constant Mill. */
public static final boolean[] Mill = new boolean[1];
public static final boolean[] DevMode = new boolean[1]; // one for normal mode one for quest mode
/** The Constant DevMode. */
public static final boolean[] DevMode = new boolean[1]; // one for
// normal mode
// one for quest
// mode
/** The Constant NetConn. */
public static final boolean[] NetConn = new boolean[1];
/** The Constant UpldDrft. */
public static final boolean[] UpldDrft = new boolean[1];
/** The Constant RndCFoil. */
public static final boolean[] RndCFoil = new boolean[1];
public static final int[] width = {300};
/** The Constant width. */
public static final int[] width = { 300 };
/** The Constant height. */
public static final int[] height = new int[1];
/** The Constant stackSize. */
public static final int[] stackSize = new int[1];
/** The Constant stackOffset. */
public static final int[] stackOffset = new int[1];
}
//public interface IO {
// probably should read this from a file, or set from GUI
// public interface IO {
// probably should read this from a file, or set from GUI
//public static final String deckFile = "all-decks2";
//public static final String boosterDeckFile = "booster-decks";
// public static final String deckFile = "all-decks2";
// public static final String boosterDeckFile = "booster-decks";
//public static final String imageBaseDir = "pics";
// public static final String imageBaseDir = "pics";
//public static final ImageIcon upIcon = new ImageIcon("up.gif");
//public static final ImageIcon downIcon = new ImageIcon("down.gif");
//public static final ImageIcon leftIcon = new ImageIcon("left.gif");
//public static final ImageIcon rightIcon = new ImageIcon("right.gif");
//}
// public static final ImageIcon upIcon = new ImageIcon("up.gif");
// public static final ImageIcon downIcon = new ImageIcon("down.gif");
// public static final ImageIcon leftIcon = new ImageIcon("left.gif");
// public static final ImageIcon rightIcon = new ImageIcon("right.gif");
// }
/**
* The Interface Ability.
*/
public interface Ability {
/** The Triggered. */
String Triggered = "Triggered";
/** The Activated. */
String Activated = "Activated";
}
/**
* The Interface Phase.
*/
public interface Phase {
public static final String Untap = "Untap";
public static final String Upkeep = "Upkeep";
public static final String Draw = "Draw";
public static final String Main1 = "Main1";
/** The Constant Untap. */
String Untap = "Untap";
public static final String Combat_Begin = "BeginCombat";
public static final String Combat_Declare_Attackers = "Declare Attackers";
public static final String Combat_Declare_Attackers_InstantAbility = "Declare Attackers - Play Instants and Abilities";
public static final String Combat_Declare_Blockers = "Declare Blockers";
public static final String Combat_Declare_Blockers_InstantAbility = "Declare Blockers - Play Instants and Abilities";
public static final String Combat_Damage = "Combat Damage";
public static final String Combat_FirstStrikeDamage = "First Strike Damage";
public static final String Combat_End = "EndCombat";
/** The Constant Upkeep. */
String Upkeep = "Upkeep";
public static final String Main2 = "Main2";
/** The Constant Draw. */
String Draw = "Draw";
public static final String End_Of_Turn = "End of Turn";
public static final String Cleanup = "Cleanup";
/** The Constant Main1. */
String Main1 = "Main1";
/** The Constant Combat_Begin. */
String Combat_Begin = "BeginCombat";
/** The Constant Combat_Declare_Attackers. */
String Combat_Declare_Attackers = "Declare Attackers";
/** The Constant Combat_Declare_Attackers_InstantAbility. */
String Combat_Declare_Attackers_InstantAbility = "Declare Attackers - Play Instants and Abilities";
/** The Constant Combat_Declare_Blockers. */
String Combat_Declare_Blockers = "Declare Blockers";
/** The Constant Combat_Declare_Blockers_InstantAbility. */
String Combat_Declare_Blockers_InstantAbility = "Declare Blockers - Play Instants and Abilities";
/** The Constant Combat_Damage. */
String Combat_Damage = "Combat Damage";
/** The Constant Combat_FirstStrikeDamage. */
String Combat_FirstStrikeDamage = "First Strike Damage";
/** The Constant Combat_End. */
String Combat_End = "EndCombat";
/** The Constant Main2. */
String Main2 = "Main2";
/** The Constant End_Of_Turn. */
String End_Of_Turn = "End of Turn";
/** The Constant Cleanup. */
String Cleanup = "Cleanup";
}
/**
* The Enum Zone.
*/
public enum Zone {
/** The Hand. */
Hand,
/** The Library. */
Library,
/** The Graveyard. */
Graveyard,
/** The Battlefield. */
Battlefield,
/** The Exile. */
Exile,
/** The Command. */
Command,
/** The Stack. */
Stack;
/**
* Smart value of.
*
* @param value
* the value
* @return the zone
*/
public static Zone smartValueOf(final String value) {
if (value == null) { return null; }
if ("All".equals(value)) { return null; }
if (value == null) {
return null;
}
if ("All".equals(value)) {
return null;
}
String valToCompate = value.trim();
for (Zone v : Zone.values()) { if (v.name().compareToIgnoreCase(valToCompate) == 0) { return v; } }
for (Zone v : Zone.values()) {
if (v.name().compareToIgnoreCase(valToCompate) == 0) {
return v;
}
}
throw new IllegalArgumentException("No element named " + value + " in enum Zone");
}
/**
* List value of.
*
* @param values
* the values
* @return the list
*/
public static List<Zone> listValueOf(final String values) {
List<Zone> result = new ArrayList<Constant.Zone>();
for (String s : values.split("[, ]+")) { result.add(smartValueOf(s)); }
for (String s : values.split("[, ]+")) {
result.add(smartValueOf(s));
}
return result;
}
}
/**
* The Interface Color.
*/
public interface Color {
/** The Black. */
String Black = "black";
/** The Blue. */
String Blue = "blue";
/** The Green. */
String Green = "green";
/** The Red. */
String Red = "red";
/** The White. */
String White = "white";
/** The Colorless. */
String Colorless = "colorless";
//color order "wubrg"
String[] Colors = {White, Blue, Black, Red, Green, Colorless};
String[] onlyColors = {White, Blue, Black, Red, Green};
// color order "wubrg"
/** The Colors. */
String[] Colors = { White, Blue, Black, Red, Green, Colorless };
/** The only colors. */
String[] onlyColors = { White, Blue, Black, Red, Green };
/** The Snow. */
String Snow = "snow";
String[] ManaColors = {White, Blue, Black, Red, Green, Colorless, Snow};
boolean[] loaded = {false};
//public static final Constant_StringHashMap[] LandColor = new Constant_StringHashMap[1];
String[] BasicLands = {"Plains", "Island", "Swamp", "Mountain", "Forest"};
/** The Mana colors. */
String[] ManaColors = { White, Blue, Black, Red, Green, Colorless, Snow };
/** The loaded. */
boolean[] loaded = { false };
// public static final Constant_StringHashMap[] LandColor = new
// Constant_StringHashMap[1];
/** The Basic lands. */
String[] BasicLands = { "Plains", "Island", "Swamp", "Mountain", "Forest" };
}
/**
* The Interface Quest.
*/
public interface Quest {
/** The fantasy quest. */
boolean[] fantasyQuest = new boolean[1];
//public static final Quest_Assignment[] qa = new Quest_Assignment[1];
// public static final Quest_Assignment[] qa = new Quest_Assignment[1];
/** The human list. */
CardList[] humanList = new CardList[1];
/** The computer list. */
CardList[] computerList = new CardList[1];
/** The human life. */
int[] humanLife = new int[1];
/** The computer life. */
int[] computerLife = new int[1];
/** The opp icon name. */
String[] oppIconName = new String[1];
}
/**
* The Interface CardTypes.
*/
public interface CardTypes {
boolean[] loaded = {false};
/** The loaded. */
boolean[] loaded = { false };
/** The card types. */
Constant_StringArrayList[] cardTypes = new Constant_StringArrayList[1];
/** The super types. */
Constant_StringArrayList[] superTypes = new Constant_StringArrayList[1];
/** The basic types. */
Constant_StringArrayList[] basicTypes = new Constant_StringArrayList[1];
/** The land types. */
Constant_StringArrayList[] landTypes = new Constant_StringArrayList[1];
/** The creature types. */
Constant_StringArrayList[] creatureTypes = new Constant_StringArrayList[1];
/** The instant types. */
Constant_StringArrayList[] instantTypes = new Constant_StringArrayList[1];
/** The sorcery types. */
Constant_StringArrayList[] sorceryTypes = new Constant_StringArrayList[1];
/** The enchantment types. */
Constant_StringArrayList[] enchantmentTypes = new Constant_StringArrayList[1];
/** The artifact types. */
Constant_StringArrayList[] artifactTypes = new Constant_StringArrayList[1];
/** The walker types. */
Constant_StringArrayList[] walkerTypes = new Constant_StringArrayList[1];
}
/**
* The Interface Keywords.
*/
public interface Keywords {
boolean[] loaded = {false};
/** The loaded. */
boolean[] loaded = { false };
/** The Non stacking list. */
Constant_StringArrayList[] NonStackingList = new Constant_StringArrayList[1];
}
} //Constant
} // Constant

View File

@@ -2,7 +2,12 @@ package forge;
import java.util.ArrayList;
/**
* The Class Constant_StringArrayList.
*/
public class Constant_StringArrayList {
public ArrayList<String> list = new ArrayList<String>();
/** The list. */
public ArrayList<String> list = new ArrayList<String>();
}

View File

@@ -3,7 +3,12 @@ package forge;
import java.util.HashMap;
import java.util.Map;
/**
* The Class Constant_StringHashMap.
*/
public class Constant_StringHashMap {
public Map<String,String> map = new HashMap<String,String>();
/** The map. */
public Map<String, String> map = new HashMap<String, String>();
}

View File

@@ -1,41 +1,65 @@
package forge;
import forge.properties.ForgeProps;
import forge.properties.NewConstants;
import javax.swing.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
import forge.properties.ForgeProps;
import forge.properties.NewConstants;
/**
* <p>CopyFiles class.</p>
*
* <p>
* CopyFiles class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class CopyFiles extends SwingWorker<Void, Integer> implements NewConstants {
private List<File> FileList;
/** The j lb. */
JLabel jLb;
/** The j b. */
JProgressBar jB;
/** The j check. */
JCheckBox jCheck;
/** The j source. */
JButton jSource;
/** The count. */
int count;
/**
* <p>Constructor for CopyFiles.</p>
*
* @param FileList a {@link java.util.List} object.
* @param jLabelTotalFiles a {@link javax.swing.JLabel} object.
* @param Jbar a {@link javax.swing.JProgressBar} object.
* @param jCheckBox a {@link javax.swing.JCheckBox} object.
* @param jButtonSource a {@link javax.swing.JButton} object.
* <p>
* Constructor for CopyFiles.
* </p>
*
* @param FileList
* a {@link java.util.List} object.
* @param jLabelTotalFiles
* a {@link javax.swing.JLabel} object.
* @param Jbar
* a {@link javax.swing.JProgressBar} object.
* @param jCheckBox
* a {@link javax.swing.JCheckBox} object.
* @param jButtonSource
* a {@link javax.swing.JButton} object.
*/
public CopyFiles(List<File> FileList, JLabel jLabelTotalFiles, JProgressBar Jbar, JCheckBox jCheckBox, JButton jButtonSource) {
public CopyFiles(final List<File> FileList, JLabel jLabelTotalFiles, JProgressBar Jbar, JCheckBox jCheckBox,
JButton jButtonSource) {
this.FileList = FileList;
jLb = jLabelTotalFiles;
jB = Jbar;
@@ -45,7 +69,7 @@ public class CopyFiles extends SwingWorker<Void, Integer> implements NewConstant
/** {@inheritDoc} */
@Override
protected Void doInBackground() {
protected final Void doInBackground() {
for (int i = 0; i < this.FileList.size(); i++) {
publish();
String cName, name, source;
@@ -66,7 +90,9 @@ public class CopyFiles extends SwingWorker<Void, Integer> implements NewConstant
int length;
while (fis.available() > 0) {
length = fis.read(buff);
if (length > 0) fos.write(buff, 0, length);
if (length > 0) {
fos.write(buff, 0, length);
}
}
fos.flush();
fis.close();
@@ -85,7 +111,7 @@ public class CopyFiles extends SwingWorker<Void, Integer> implements NewConstant
/** {@inheritDoc} */
@Override
protected void done() {
protected final void done() {
jLb.setText("All files were copied successfully.");
jB.setIndeterminate(false);
jCheck.setEnabled(true);

View File

@@ -6,129 +6,321 @@
package forge;
/**
* The class Counters.
*
*
* @author Clemens Koza
* @version V0.0 17.02.2010
*/
public enum Counters {
/** The AGE. */
AGE(),
/** The ARROW. */
ARROW(),
/** The ARROWHEAD. */
ARROWHEAD(),
/** The AWAKENING. */
AWAKENING(),
/** The BLAZE. */
BLAZE(),
/** The BLOOD. */
BLOOD(),
/** The BOUNTY. */
BOUNTY(),
/** The BRIBERY. */
BRIBERY(),
/** The CARRION. */
CARRION(),
/** The CHARGE. */
CHARGE(),
/** The CORPSE. */
CORPSE(),
/** The CREDIT. */
CREDIT(),
/** The CURRENCY. */
CURRENCY(),
/** The DEATH. */
DEATH(),
/** The DELAY. */
DELAY(),
/** The DEPLETION. */
DEPLETION(),
/** The DEVOTION. */
DEVOTION(),
/** The DIVINITY. */
DIVINITY(),
/** The DOOM. */
DOOM(),
/** The ENERGY. */
ENERGY(),
/** The EON. */
EON(),
/** The FADE. */
FADE(),
/** The FATE. */
FATE(),
/** The FEATHER. */
FEATHER(),
/** The FLOOD. */
FLOOD(),
/** The FUNGUS. */
FUNGUS(),
/** The FUSE. */
FUSE(),
/** The GLYPH. */
GLYPH(),
/** The GOLD. */
GOLD(),
/** The GROWTH. */
GROWTH(),
/** The HATCHLING. */
HATCHLING(),
/** The HEALING. */
HEALING(),
/** The HOOFPRINT. */
HOOFPRINT(),
/** The HOURGLASS. */
HOURGLASS(),
/** The ICE. */
ICE(),
/** The INFECTION. */
INFECTION(),
/** The INTERVENTION. */
INTERVENTION(),
/** The JAVELIN. */
JAVELIN(),
/** The KI. */
KI(),
/** The LEVEL. */
LEVEL("Level"),
/** The LORE. */
LORE(),
/** The LOYALTY. */
LOYALTY(),
/** The LUCK. */
LUCK(),
/** The M0 m1. */
M0M1("-0/-1"),
/** The M0 m2. */
M0M2("-0/-2"),
/** The M1 m0. */
M1M0("-1/-0"),
/** The M1 m1. */
M1M1("-1/-1"),
/** The M2 m1. */
M2M1("-2/-1"),
/** The M2 m2. */
M2M2("-2/-2"),
/** The MANA. */
MANA(),
/** The MINE. */
MINE(),
/** The MINING. */
MINING(),
/** The MIRE. */
MIRE(),
/** The OMEN. */
OMEN(),
/** The ORE. */
ORE(),
/** The PAGE. */
PAGE(),
/** The PAIN. */
PAIN(),
/** The PARALYZATION. */
PARALYZATION(),
/** The PETAL. */
PETAL(),
/** The PIN. */
PIN(),
/** The PLAGUE. */
PLAGUE(),
/** The PRESSURE. */
PRESSURE(),
/** The PHYLACTERY. */
PHYLACTERY,
/** The POLYP. */
POLYP(),
/** The PUPA. */
PUPA(),
/** The P0 p1. */
P0P1("+0/+1"),
/** The P1 p0. */
P1P0("+1/+0"),
/** The P1 p1. */
P1P1("+1/+1"),
/** The P1 p2. */
P1P2("+1/+2"),
/** The P2 p2. */
P2P2("+2/+2"),
/** The QUEST. */
QUEST(),
/** The SCREAM. */
SCREAM(),
/** The SHELL. */
SHELL(),
/** The SHIELD. */
SHIELD(),
/** The SHRED. */
SHRED(),
/** The SLEEP. */
SLEEP(),
/** The SLEIGHT. */
SLEIGHT(),
/** The SOOT. */
SOOT(),
/** The SPORE. */
SPORE(),
/** The STORAGE. */
STORAGE(),
/** The STUDY. */
STUDY(),
/** The TIDE. */
TIDE(),
/** The TIME. */
TIME(),
/** The TOWER. */
TOWER("tower"),
/** The TRAINING. */
TRAINING(),
/** The TRAP. */
TRAP(),
/** The TREASURE. */
TREASURE(),
/** The VELOCITY. */
VELOCITY(),
/** The VERSE. */
VERSE(),
/** The VITALITY. */
VITALITY(),
/** The WAGE. */
WAGE(),
/** The WIND. */
WIND(),
/** The WISH. */
WISH();
private String name;
/**
* <p>Constructor for Counters.</p>
* <p>
* Constructor for Counters.
* </p>
*/
private Counters() {
this.name = name().substring(0, 1).toUpperCase() + name().substring(1).toLowerCase();
}
/**
* <p>Constructor for Counters.</p>
*
* @param name a {@link java.lang.String} object.
* <p>
* Constructor for Counters.
* </p>
*
* @param name
* a {@link java.lang.String} object.
*/
private Counters(final String nameIn) {
this.name = nameIn;
}
/**
* <p>Getter for the field <code>name</code>.</p>
*
* <p>
* Getter for the field <code>name</code>.
* </p>
*
* @return a {@link java.lang.String} object.
*/
public String getName() {
@@ -136,9 +328,12 @@ public enum Counters {
}
/**
* <p>getType.</p>
*
* @param name a {@link java.lang.String} object.
* <p>
* getType.
* </p>
*
* @param name
* a {@link java.lang.String} object.
* @return a {@link forge.Counters} object.
*/
public static Counters getType(final String name) {

View File

@@ -6,8 +6,10 @@ import forge.card.spellability.SpellAbility;
//handles "until end of turn" and "at end of turn" commands from cards
/**
* <p>EndOfTurn class.</p>
*
* <p>
* EndOfTurn class.
* </p>
*
* @author Forge
* @version $Id$
*/
@@ -20,44 +22,55 @@ public class EndOfTurn implements java.io.Serializable {
private CommandList last = new CommandList();
/**
* <p>addAt.</p>
*
* @param c a {@link forge.Command} object.
* <p>
* addAt.
* </p>
*
* @param c
* a {@link forge.Command} object.
*/
public final void addAt(final Command c) {
at.add(c);
}
/**
* <p>addUntil.</p>
*
* @param c a {@link forge.Command} object.
* <p>
* addUntil.
* </p>
*
* @param c
* a {@link forge.Command} object.
*/
public final void addUntil(final Command c) {
until.add(c);
}
/**
* <p>addLast.</p>
*
* @param c a {@link forge.Command} object.
* <p>
* addLast.
* </p>
*
* @param c
* a {@link forge.Command} object.
*/
public final void addLast(final Command c) {
last.add(c);
}
/**
* <p>executeAt.</p>
* <p>
* executeAt.
* </p>
*/
public final void executeAt() {
//Pyrohemia and Pestilence
// Pyrohemia and Pestilence
CardList all = AllZoneUtil.getCardsIn(Zone.Battlefield);
GameActionUtil.endOfTurn_Wall_Of_Reverence();
GameActionUtil.endOfTurn_Lighthouse_Chronologist();
//reset mustAttackEntity for me
// reset mustAttackEntity for me
AllZone.getPhase().getPlayerTurn().setMustAttackEntity(null);
GameActionUtil.removeAttackedBlockedThisTurn();
@@ -65,9 +78,7 @@ public class EndOfTurn implements java.io.Serializable {
AllZone.getStaticEffects().rePopulateStateBasedList();
for (Card c : all) {
if (!c.isFaceDown()
&& c.hasKeyword("At the beginning of the end step, sacrifice CARDNAME."))
{
if (!c.isFaceDown() && c.hasKeyword("At the beginning of the end step, sacrifice CARDNAME.")) {
final Card card = c;
final SpellAbility sac = new Ability(card, "0") {
@Override
@@ -84,9 +95,7 @@ public class EndOfTurn implements java.io.Serializable {
AllZone.getStack().addSimultaneousStackEntry(sac);
}
if (!c.isFaceDown()
&& c.hasKeyword("At the beginning of the end step, exile CARDNAME."))
{
if (!c.isFaceDown() && c.hasKeyword("At the beginning of the end step, exile CARDNAME.")) {
final Card card = c;
final SpellAbility exile = new Ability(card, "0") {
@Override
@@ -103,9 +112,7 @@ public class EndOfTurn implements java.io.Serializable {
AllZone.getStack().addSimultaneousStackEntry(exile);
}
if (!c.isFaceDown()
&& c.hasKeyword("At the beginning of the end step, destroy CARDNAME."))
{
if (!c.isFaceDown() && c.hasKeyword("At the beginning of the end step, destroy CARDNAME.")) {
final Card card = c;
final SpellAbility destroy = new Ability(card, "0") {
@Override
@@ -122,7 +129,7 @@ public class EndOfTurn implements java.io.Serializable {
AllZone.getStack().addSimultaneousStackEntry(destroy);
}
//Berserk is using this, so don't check isFaceDown()
// Berserk is using this, so don't check isFaceDown()
if (c.hasKeyword("At the beginning of the next end step, destroy CARDNAME if it attacked this turn.")) {
if (c.getCreatureAttackedThisTurn()) {
final Card card = c;
@@ -151,8 +158,9 @@ public class EndOfTurn implements java.io.Serializable {
public void resolve() {
if (AllZoneUtil.isCardInPlay(vale)) {
vale.addController(vale.getController().getOpponent());
//AllZone.getGameAction().changeController(
// new CardList(vale), vale.getController(), vale.getController().getOpponent());
// AllZone.getGameAction().changeController(
// new CardList(vale), vale.getController(),
// vale.getController().getOpponent());
vale.removeExtrinsicKeyword("An opponent gains control of CARDNAME at the beginning of the next end step.");
}
@@ -165,9 +173,8 @@ public class EndOfTurn implements java.io.Serializable {
AllZone.getStack().addSimultaneousStackEntry(change);
}
if (c.getName().equals("Erg Raiders") && !c.getCreatureAttackedThisTurn()
&& !c.hasSickness() && AllZone.getPhase().isPlayerTurn(c.getController()))
{
if (c.getName().equals("Erg Raiders") && !c.getCreatureAttackedThisTurn() && !c.hasSickness()
&& AllZone.getPhase().isPlayerTurn(c.getController())) {
final Card raider = c;
final SpellAbility change = new Ability(raider, "0") {
@Override
@@ -186,9 +193,8 @@ public class EndOfTurn implements java.io.Serializable {
}
if (c.hasKeyword("At the beginning of your end step, sacrifice this creature unless it attacked this turn.")
&& !c.getCreatureAttackedThisTurn()
/* && !(c.getTurnInZone() == AllZone.getPhase().getTurn())*/
&& AllZone.getPhase().isPlayerTurn(c.getController()))
{
/* && !(c.getTurnInZone() == AllZone.getPhase().getTurn()) */
&& AllZone.getPhase().isPlayerTurn(c.getController())) {
final Card source = c;
final SpellAbility change = new Ability(source, "0") {
@Override
@@ -206,9 +212,7 @@ public class EndOfTurn implements java.io.Serializable {
}
if (c.hasKeyword("At the beginning of your end step, destroy this creature if it didn't attack this turn.")
&& !c.getCreatureAttackedThisTurn()
&& AllZone.getPhase().isPlayerTurn(c.getController()))
{
&& !c.getCreatureAttackedThisTurn() && AllZone.getPhase().isPlayerTurn(c.getController())) {
final Card source = c;
final SpellAbility change = new Ability(source, "0") {
@Override
@@ -226,8 +230,7 @@ public class EndOfTurn implements java.io.Serializable {
}
if (c.hasKeyword("At the beginning of your end step, return CARDNAME to its owner's hand.")
&& AllZone.getPhase().isPlayerTurn(c.getController()))
{
&& AllZone.getPhase().isPlayerTurn(c.getController())) {
final Card source = c;
final SpellAbility change = new Ability(source, "0") {
@Override
@@ -247,10 +250,8 @@ public class EndOfTurn implements java.io.Serializable {
}
execute(at);
CardList all2 = AllZoneUtil.getCardsIn(Zone.Battlefield);
for (Card c : all2) {
c.clearMustBlockCards();
@@ -259,11 +260,12 @@ public class EndOfTurn implements java.io.Serializable {
}
}
} //executeAt()
} // executeAt()
/**
* <p>executeUntil.</p>
* <p>
* executeUntil.
* </p>
*/
public final void executeUntil() {
execute(until);
@@ -271,8 +273,10 @@ public class EndOfTurn implements java.io.Serializable {
}
/**
* <p>sizeAt.</p>
*
* <p>
* sizeAt.
* </p>
*
* @return a int.
*/
public final int sizeAt() {
@@ -280,8 +284,10 @@ public class EndOfTurn implements java.io.Serializable {
}
/**
* <p>sizeUntil.</p>
*
* <p>
* sizeUntil.
* </p>
*
* @return a int.
*/
public final int sizeUntil() {
@@ -289,8 +295,10 @@ public class EndOfTurn implements java.io.Serializable {
}
/**
* <p>sizeLast.</p>
*
* <p>
* sizeLast.
* </p>
*
* @return a int.
*/
public final int sizeLast() {
@@ -298,9 +306,12 @@ public class EndOfTurn implements java.io.Serializable {
}
/**
* <p>execute.</p>
*
* @param c a {@link forge.CommandList} object.
* <p>
* execute.
* </p>
*
* @param c
* a {@link forge.CommandList} object.
*/
private void execute(final CommandList c) {
int length = c.size();
@@ -310,4 +321,4 @@ public class EndOfTurn implements java.io.Serializable {
}
}
} //end class EndOfTurn
} // end class EndOfTurn

View File

@@ -1,12 +1,16 @@
package forge;
import javax.swing.*;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* ExternalPanel.java
@@ -14,10 +18,10 @@ import java.awt.event.WindowEvent;
* Created on 13.08.2009
*/
/**
* The class ExternalPanel. A panel with which some other component can be shown in an external window.
*
* The class ExternalPanel. A panel with which some other component can be shown
* in an external window.
*
* @author Clemens Koza
* @version V0.0 13.08.2009
*/
@@ -29,19 +33,26 @@ public class ExternalPanel extends JPanel {
private JFrame frame;
/**
* <p>Constructor for ExternalPanel.</p>
*
* @param child a {@link java.awt.Component} object.
* <p>
* Constructor for ExternalPanel.
* </p>
*
* @param child
* a {@link java.awt.Component} object.
*/
public ExternalPanel(final Component child) {
this(child, BorderLayout.EAST);
}
/**
* <p>Constructor for ExternalPanel.</p>
*
* @param child a {@link java.awt.Component} object.
* @param side a {@link java.lang.String} object.
* <p>
* Constructor for ExternalPanel.
* </p>
*
* @param child
* a {@link java.awt.Component} object.
* @param side
* a {@link java.lang.String} object.
*/
public ExternalPanel(final Component child, final String side) {
super(new BorderLayout());
@@ -55,9 +66,12 @@ public class ExternalPanel extends JPanel {
}
/**
* <p>setHeadSide.</p>
*
* @param side a {@link java.lang.String} object.
* <p>
* setHeadSide.
* </p>
*
* @param side
* a {@link java.lang.String} object.
*/
public final void setHeadSide(final String side) {
remove(head);

View File

@@ -1,9 +1,5 @@
package forge;
import forge.error.ErrorViewer;
import forge.properties.ForgeProps;
import forge.properties.NewConstants.LANG.Gui_DownloadPictures.ERRORS;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
@@ -19,10 +15,16 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import forge.error.ErrorViewer;
import forge.properties.ForgeProps;
import forge.properties.NewConstants.LANG.Gui_DownloadPictures.ERRORS;
// TODO: Auto-generated Javadoc
/**
* <p>FileUtil class.</p>
*
* <p>
* FileUtil class.
* </p>
*
* @author Forge
* @version $Id$
*/
@@ -33,9 +35,12 @@ public final class FileUtil {
}
/**
* <p>doesFileExist.</p>
*
* @param filename a {@link java.lang.String} object.
* <p>
* doesFileExist.
* </p>
*
* @param filename
* a {@link java.lang.String} object.
* @return a boolean.
*/
public static boolean doesFileExist(final String filename) {
@@ -44,24 +49,32 @@ public final class FileUtil {
}
/**
* <p>writeFile.</p>
*
* @param filename a {@link java.lang.String} object.
* @param data a {@link java.util.List} object.
* <p>
* writeFile.
* </p>
*
* @param filename
* a {@link java.lang.String} object.
* @param data
* a {@link java.util.List} object.
*/
public static void writeFile(final String filename, final List<String> data) {
writeFile(new File(filename), data);
}
//writes each element of ArrayList on a separate line
//this is used to write a file of Strings
//this will create a new file if needed
//if filename already exists, it is deleted
// writes each element of ArrayList on a separate line
// this is used to write a file of Strings
// this will create a new file if needed
// if filename already exists, it is deleted
/**
* <p>writeFile.</p>
*
* @param file a {@link java.io.File} object.
* @param data a {@link java.util.List} object.
* <p>
* writeFile.
* </p>
*
* @param file
* a {@link java.io.File} object.
* @param data
* a {@link java.util.List} object.
*/
public static void writeFile(final File file, final List<String> data) {
try {
@@ -78,25 +91,31 @@ public final class FileUtil {
ErrorViewer.showError(ex);
throw new RuntimeException("FileUtil : writeFile() error, problem writing file - " + file + " : " + ex);
}
} //writeAllDecks()
} // writeAllDecks()
/**
* <p>readFile.</p>
*
* @param filename a {@link java.lang.String} object.
* <p>
* readFile.
* </p>
*
* @param filename
* a {@link java.lang.String} object.
* @return a {@link java.util.ArrayList} object.
*/
public static ArrayList<String> readFile(final String filename) {
return readFile(new File(filename));
}
//reads line by line and adds each line to the ArrayList
//this will return blank lines as well
//if filename not found, returns an empty ArrayList
// reads line by line and adds each line to the ArrayList
// this will return blank lines as well
// if filename not found, returns an empty ArrayList
/**
* <p>readFile.</p>
*
* @param file a {@link java.io.File} object.
* <p>
* readFile.
* </p>
*
* @param file
* a {@link java.io.File} object.
* @return a {@link java.util.ArrayList} object.
*/
public static ArrayList<String> readFile(final File file) {
@@ -108,7 +127,6 @@ public final class FileUtil {
return list;
}
in = new BufferedReader(new FileReader(file));
String line;
@@ -121,31 +139,34 @@ public final class FileUtil {
}
return list;
} //readFile()
public static void downloadUrlIntoFile(final String url, final File target)
{
try{
} // readFile()
/**
* Download url into file.
*
* @param url the url
* @param target the target
*/
public static void downloadUrlIntoFile(final String url, final File target) {
try {
byte[] buf = new byte[1024];
int len;
Proxy p = Proxy.NO_PROXY;
BufferedInputStream in = new BufferedInputStream(new URL(url).openConnection(p).getInputStream());
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(target));
//while - read and write file
// while - read and write file
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}//while - read and write file
} // while - read and write file
in.close();
out.flush();
out.close();
}
catch (IOException ioex)
{
} catch (IOException ioex) {
ErrorViewer.showError(ioex, ForgeProps.getLocalized(ERRORS.OTHER), "deck_temp.html", url);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -4,48 +4,60 @@ import java.util.ArrayList;
import forge.card.spellability.SpellAbility;
// TODO: Auto-generated Javadoc
/**
* <p>Abstract Player class.</p>
*
* <p>
* Abstract Player class.
* </p>
*
* @author Forge
* @version $Id: Player.java 10091 2011-08-30 16:11:21Z Sloth $
*/
public abstract class GameEntity extends MyObservable {
private String name = "";
private int preventNextDamage = 0;
/** The enchanted by. */
protected ArrayList<Card> enchantedBy = new ArrayList<Card>();
/**
* <p>Getter for the field <code>name</code>.</p>
*
* <p>
* Getter for the field <code>name</code>.
* </p>
*
* @return a {@link java.lang.String} object.
*/
public String getName() {
return name;
}
/**
* <p>Setter for the field <code>name</code>.</p>
*
* @param s a {@link java.lang.String} object.
* <p>
* Setter for the field <code>name</code>.
* </p>
*
* @param s
* a {@link java.lang.String} object.
*/
public void setName(String s) {
name = s;
}
//////////////////////////
// ////////////////////////
//
// methods for handling damage
//
//////////////////////////
// ////////////////////////
/**
* <p>addDamage.</p>
*
* @param damage a int.
* @param source a {@link forge.Card} object.
* <p>
* addDamage.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.Card} object.
*/
public void addDamage(final int damage, final Card source) {
int damageToDo = damage;
@@ -57,10 +69,14 @@ public abstract class GameEntity extends MyObservable {
}
/**
* <p>addDamageWithoutPrevention.</p>
*
* @param damage a int.
* @param source a {@link forge.Card} object.
* <p>
* addDamageWithoutPrevention.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.Card} object.
*/
public void addDamageWithoutPrevention(final int damage, final Card source) {
int damageToDo = damage;
@@ -70,27 +86,39 @@ public abstract class GameEntity extends MyObservable {
addDamageAfterPrevention(damageToDo, source, false);
}
//This function handles damage after replacement and prevention effects are applied
// This function handles damage after replacement and prevention effects are
// applied
/**
* <p>addDamageAfterPrevention.</p>
*
* @param damage a int.
* @param source a {@link forge.Card} object.
* @param isCombat a boolean.
* <p>
* addDamageAfterPrevention.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.Card} object.
* @param isCombat
* a boolean.
*/
public void addDamageAfterPrevention(final int damage, final Card source, final boolean isCombat) {
}
/**
* <p>predictDamage.</p>
*
* @param damage a int.
* @param source a {@link forge.Card} object.
* @param isCombat a boolean.
* <p>
* predictDamage.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.Card} object.
* @param isCombat
* a boolean.
* @return a int.
*/
//This function helps the AI calculate the actual amount of damage an effect would deal
// This function helps the AI calculate the actual amount of damage an
// effect would deal
public int predictDamage(final int damage, final Card source, final boolean isCombat) {
int restDamage = damage;
@@ -101,26 +129,38 @@ public abstract class GameEntity extends MyObservable {
return restDamage;
}
//This should be also usable by the AI to forecast an effect (so it must not change the game state)
// This should be also usable by the AI to forecast an effect (so it must
// not change the game state)
/**
* <p>staticDamagePrevention.</p>
*
* @param damage a int.
* @param source a {@link forge.Card} object.
* @param isCombat a boolean.
* <p>
* staticDamagePrevention.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.Card} object.
* @param isCombat
* a boolean.
* @return a int.
*/
public int staticDamagePrevention(final int damage, final Card source, final boolean isCombat) {
return 0;
}
//This should be also usable by the AI to forecast an effect (so it must not change the game state)
// This should be also usable by the AI to forecast an effect (so it must
// not change the game state)
/**
* <p>staticReplaceDamage.</p>
*
* @param damage a int.
* @param source a {@link forge.Card} object.
* @param isCombat a boolean.
* <p>
* staticReplaceDamage.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.Card} object.
* @param isCombat
* a boolean.
* @return a int.
*/
public int staticReplaceDamage(final int damage, Card source, boolean isCombat) {
@@ -128,11 +168,16 @@ public abstract class GameEntity extends MyObservable {
}
/**
* <p>replaceDamage.</p>
*
* @param damage a int.
* @param source a {@link forge.Card} object.
* @param isCombat a boolean.
* <p>
* replaceDamage.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.Card} object.
* @param isCombat
* a boolean.
* @return a int.
*/
public int replaceDamage(final int damage, Card source, boolean isCombat) {
@@ -140,36 +185,46 @@ public abstract class GameEntity extends MyObservable {
}
/**
* <p>preventDamage.</p>
*
* @param damage a int.
* @param source a {@link forge.Card} object.
* @param isCombat a boolean.
* <p>
* preventDamage.
* </p>
*
* @param damage
* a int.
* @param source
* a {@link forge.Card} object.
* @param isCombat
* a boolean.
* @return a int.
*/
public int preventDamage(final int damage, Card source, boolean isCombat) {
return 0;
}
//////////////////////////
// ////////////////////////
//
// methods for handling Damage Prevention
//
//////////////////////////
// ////////////////////////
//PreventNextDamage
// PreventNextDamage
/**
* <p>Setter for the field <code>preventNextDamage</code>.</p>
*
* @param n a int.
* <p>
* Setter for the field <code>preventNextDamage</code>.
* </p>
*
* @param n
* a int.
*/
public void setPreventNextDamage(int n) {
preventNextDamage = n;
}
/**
* <p>Getter for the field <code>preventNextDamage</code>.</p>
*
* <p>
* Getter for the field <code>preventNextDamage</code>.
* </p>
*
* @return a int.
*/
public int getPreventNextDamage() {
@@ -177,65 +232,106 @@ public abstract class GameEntity extends MyObservable {
}
/**
* <p>addPreventNextDamage.</p>
*
* @param n a int.
* <p>
* addPreventNextDamage.
* </p>
*
* @param n
* a int.
*/
public void addPreventNextDamage(int n) {
preventNextDamage += n;
}
/**
* <p>subtractPreventNextDamage.</p>
*
* @param n a int.
* <p>
* subtractPreventNextDamage.
* </p>
*
* @param n
* a int.
*/
public void subtractPreventNextDamage(int n) {
preventNextDamage -= n;
}
/**
* <p>resetPreventNextDamage.</p>
* <p>
* resetPreventNextDamage.
* </p>
*/
public void resetPreventNextDamage() {
preventNextDamage = 0;
}
public boolean hasKeyword(String keyword){
return false;
}
/**
* Checks for keyword.
*
* @param sa
* @return a boolean
* @param keyword the keyword
* @return true, if successful
*/
public boolean canTarget(SpellAbility sa) {
public boolean hasKeyword(String keyword) {
return false;
}
/**
* Can target.
*
* @param sa the sa
* @return a boolean
*/
public boolean canTarget(SpellAbility sa) {
return false;
}
/**
* Checks if is valid.
*
* @param Restrictions the restrictions
* @param sourceController the source controller
* @param source the source
* @return true, if is valid
*/
public boolean isValid(final String Restrictions[], final Player sourceController, final Card source) {
for (int i = 0; i < Restrictions.length; i++) {
if (isValid(Restrictions[i], sourceController, source)) return true;
if (isValid(Restrictions[i], sourceController, source))
return true;
}
return false;
}//isValid
}// isValid
/**
* Checks if is valid.
*
* @param Restriction the restriction
* @param sourceController the source controller
* @param source the source
* @return true, if is valid
*/
public boolean isValid(final String Restriction, final Player sourceController, final Card source) {
return false;
}
/**
* Checks for property.
*
* @param Property the property
* @param sourceController the source controller
* @param source the source
* @return true, if successful
*/
public boolean hasProperty(String Property, final Player sourceController, final Card source) {
return false;
}
// GameEntities can now be Enchanted
/**
* <p>Getter for the field <code>enchantedBy</code>.</p>
*
* <p>
* Getter for the field <code>enchantedBy</code>.
* </p>
*
* @return a {@link java.util.ArrayList} object.
*/
public final ArrayList<Card> getEnchantedBy() {
@@ -243,28 +339,35 @@ public abstract class GameEntity extends MyObservable {
}
/**
* <p>Setter for the field <code>enchantedBy</code>.</p>
*
* @param list a {@link java.util.ArrayList} object.
* <p>
* Setter for the field <code>enchantedBy</code>.
* </p>
*
* @param list
* a {@link java.util.ArrayList} object.
*/
public final void setEnchantedBy(final ArrayList<Card> list) {
enchantedBy = list;
}
/**
* <p>isEnchanted.</p>
*
* <p>
* isEnchanted.
* </p>
*
* @return a boolean.
*/
public final boolean isEnchanted() {
return enchantedBy.size() != 0;
}
/**
* <p>addEnchantedBy.</p>
*
* @param c a {@link forge.Card} object.
* <p>
* addEnchantedBy.
* </p>
*
* @param c
* a {@link forge.Card} object.
*/
public final void addEnchantedBy(final Card c) {
enchantedBy.add(c);
@@ -272,17 +375,22 @@ public abstract class GameEntity extends MyObservable {
}
/**
* <p>removeEnchantedBy.</p>
*
* @param c a {@link forge.Card} object.
* <p>
* removeEnchantedBy.
* </p>
*
* @param c
* a {@link forge.Card} object.
*/
public final void removeEnchantedBy(final Card c) {
enchantedBy.remove(c);
this.updateObservers();
}
/**
* <p>unEnchantAllCards.</p>
* <p>
* unEnchantAllCards.
* </p>
*/
public final void unEnchantAllCards() {
for (int i = 0; i < enchantedBy.size(); i++) {
@@ -290,12 +398,11 @@ public abstract class GameEntity extends MyObservable {
}
}
////////////////////////////////
// //////////////////////////////
//
// generic Object overrides
//
/////////////////////////////////
// ///////////////////////////////
/** {@inheritDoc} */
@Override

View File

@@ -66,7 +66,7 @@ public class Gui_DownloadPictures_LQ extends GuiDownloader {
list.add(cardPlay[i]);
}
}
//add missing tokens to the list of things to download
File filebase = ForgeProps.getFile(IMAGE_TOKEN);
for (int i = 0; i < cardTokenLQ.length; i++) {

View File

@@ -1,33 +1,46 @@
package forge;
import forge.properties.ForgeProps;
import forge.properties.NewConstants.LANG.Gui_DownloadPrices.DOWNLOADPRICES;
import forge.properties.NewConstants.QUEST;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.Point;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import forge.properties.ForgeProps;
import forge.properties.NewConstants.LANG.Gui_DownloadPrices.DOWNLOADPRICES;
import forge.properties.NewConstants.QUEST;
/**
* <p>Gui_DownloadPrices class.</p>
*
* <p>
* Gui_DownloadPrices class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class Gui_DownloadPrices extends JFrame {
/** Constant <code>serialVersionUID=1L</code> */
/** Constant <code>serialVersionUID=1L</code>. */
private static final long serialVersionUID = 1L;
private JPanel jContentPane = null;
private JButton jButton = null;
/**
* This is the default constructor
* This is the default constructor.
*/
public Gui_DownloadPrices() {
super();
@@ -35,7 +48,7 @@ public class Gui_DownloadPrices extends JFrame {
}
/**
* This method initializes this
* This method initializes this.
*/
private void initialize() {
this.setSize(386, 200);
@@ -44,8 +57,8 @@ public class Gui_DownloadPrices extends JFrame {
}
/**
* This method initializes jContentPane
*
* This method initializes jContentPane.
*
* @return javax.swing.JPanel
*/
private JPanel getJContentPane() {
@@ -58,8 +71,8 @@ public class Gui_DownloadPrices extends JFrame {
}
/**
* This method initializes jButton
*
* This method initializes jButton.
*
* @return javax.swing.JButton
*/
private JButton getJButton() {
@@ -70,9 +83,10 @@ public class Gui_DownloadPrices extends JFrame {
jButton.setSize(158, 89);
jButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
if (jButton.getText().equals("Done!"))
public void actionPerformed(final java.awt.event.ActionEvent e) {
if (jButton.getText().equals("Done!")) {
Gui_DownloadPrices.this.dispose();
}
BufferedInputStream in = null;
BufferedOutputStream out = null;
@@ -85,14 +99,12 @@ public class Gui_DownloadPrices extends JFrame {
String s = "Downloading";
try {
in = new BufferedInputStream(new URL(url)
.openConnection(p).getInputStream());
in = new BufferedInputStream(new URL(url).openConnection(p).getInputStream());
out = new BufferedOutputStream(new FileOutputStream(f));
jButton.setText(ForgeProps.getLocalized(DOWNLOADPRICES.DOWNLOADING));
jContentPane.paintImmediately(jButton.getBounds());
int len = 0;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
@@ -100,8 +112,7 @@ public class Gui_DownloadPrices extends JFrame {
if (++x % 50 == 0) {
s += ".";
jButton.setText(s);
jContentPane.paintImmediately(jButton
.getBounds());
jContentPane.paintImmediately(jButton.getBounds());
if (x >= 300) {
x = 0;
@@ -116,14 +127,16 @@ public class Gui_DownloadPrices extends JFrame {
return;
} finally {
try {
if (in != null)
if (in != null) {
in.close();
if (out != null)
}
if (out != null) {
out.close();
}
} catch (IOException ex) {
return;
}
}// while - read and write file
} // while - read and write file
FileReader fr = null;
FileWriter fw = null;
@@ -144,7 +157,7 @@ public class Gui_DownloadPrices extends JFrame {
x = 0;
s = "Compiling";
while (line != null && !line.equals("")) {
String ll[] = line.split("\\|");
String[] ll = line.split("\\|");
if (ll[0].contains("(")) {
int indx = ll[0].indexOf(" (");
@@ -160,21 +173,25 @@ public class Gui_DownloadPrices extends JFrame {
if (cp >= inp) {
fScl = 1 - (float) inp / (float) cp;
if (fScl > .333)
if (fScl > .333) {
cp = cp / 2;
}
} else {
fScl = 1 - (float) cp / (float) inp;
if (fScl > .333)
if (fScl > .333) {
inp = inp / 2;
}
}
int ap = (cp + inp) / 2;
if (ap < 7)
if (ap < 7) {
ap += 10;
}
prices.put(ll[0], ap);
} else {
if (inp < 7)
if (inp < 7) {
inp += 10;
}
prices.put(ll[0], inp);
}
@@ -185,8 +202,7 @@ public class Gui_DownloadPrices extends JFrame {
if (++x % 100 == 0) {
s += ".";
jButton.setText(s);
jContentPane.paintImmediately(jButton
.getBounds());
jContentPane.paintImmediately(jButton.getBounds());
if (x >= 500) {
x = 0;
@@ -195,14 +211,12 @@ public class Gui_DownloadPrices extends JFrame {
}
}
String pfn = ForgeProps.getFile(QUEST.PRICE)
.getAbsolutePath();
String pfn = ForgeProps.getFile(QUEST.PRICE).getAbsolutePath();
String pfnb = pfn.replace(".txt", ".bak");
File ff = new File(pfn);
ff.renameTo(new File(pfnb));
fw = new FileWriter(ForgeProps
.getFile(QUEST.PRICE));
fw = new FileWriter(ForgeProps.getFile(QUEST.PRICE));
BufferedWriter outBW = new BufferedWriter(fw);
// Collection<String> keys = prices.keySet();
@@ -213,24 +227,22 @@ public class Gui_DownloadPrices extends JFrame {
for (int i = 0; i < keys.size(); i++) {
// keys.add(key);
String k = keys.get(i);
if (k.equals("Plains") || k.equals("Island")
|| k.equals("Swamp")
|| k.equals("Mountain")
if (k.equals("Plains") || k.equals("Island") || k.equals("Swamp") || k.equals("Mountain")
|| k.equals("Forest"))
{
outBW.write(k + "=5\r\n");
else if (k.equals("Snow-Covered Plains")
|| k.equals("Snow-Covered Island")
|| k.equals("Snow-Covered Swamp")
|| k.equals("Snow-Covered Mountain")
} else if (k.equals("Snow-Covered Plains") || k.equals("Snow-Covered Island")
|| k.equals("Snow-Covered Swamp") || k.equals("Snow-Covered Mountain")
|| k.equals("Snow-Covered Forest"))
{
outBW.write(k + "=10\r\n");
else
outBW.write(keys.get(i) + "="
+ prices.get(keys.get(i)) + "\r\n");
} else {
outBW.write(keys.get(i) + "=" + prices.get(keys.get(i)) + "\r\n");
}
if (i % 100 == 0)
if (i % 100 == 0) {
outBW.flush();
}
}
outBW.flush();
@@ -244,10 +256,12 @@ public class Gui_DownloadPrices extends JFrame {
return;
} finally {
try {
if (fr != null)
if (fr != null) {
fr.close();
if (fw != null)
}
if (fw != null) {
fw.close();
}
} catch (IOException ex) {
return;
}