mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
Revert module separation to make another commit that would keep files' history
This commit is contained in:
999
.gitattributes
vendored
999
.gitattributes
vendored
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,11 @@
|
||||
<artifactId>forge-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>forge</groupId>
|
||||
<artifactId>forge-game</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -18,15 +18,5 @@
|
||||
<artifactId>forge-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.googlecode</groupId>
|
||||
<artifactId>minlog</artifactId>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>forge</groupId>
|
||||
<artifactId>forge-ai</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package forge;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
|
||||
public class ImageCacheBridge {
|
||||
|
||||
public static Methods instance;
|
||||
|
||||
public interface Methods {
|
||||
String getImageKey(InventoryItem cp, boolean altState);
|
||||
String getTokenKey(String imageName);
|
||||
String getMorphImage();
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package forge;
|
||||
|
||||
|
||||
public class PreferencesBridge {
|
||||
public static PreferencesSet Instance;
|
||||
|
||||
public interface PreferencesSet {
|
||||
|
||||
public abstract boolean getEnableAiCheats();
|
||||
|
||||
public abstract boolean getCloneModeSource();
|
||||
|
||||
public abstract String getLogEntryType();
|
||||
|
||||
public abstract String getCurrentAiProfile();
|
||||
|
||||
public abstract boolean canRandomFoil();
|
||||
|
||||
public abstract boolean isManaBurnEnabled();
|
||||
|
||||
public abstract boolean areBlocksFree();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +1,8 @@
|
||||
/** Forge Card Game. */
|
||||
package forge.game;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @author Max
|
||||
*
|
||||
*/
|
||||
package forge.game;
|
||||
@@ -1,39 +1,39 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Command interface.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: Command.java 21051 2013-04-17 11:48:06Z Max mtg $
|
||||
*/
|
||||
public interface Command extends java.io.Serializable, Runnable {
|
||||
/** Constant <code>Blank</code>. */
|
||||
public final Command BLANK = new Command() {
|
||||
|
||||
private static final long serialVersionUID = 2689172297036001710L;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Command interface.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public interface Command extends java.io.Serializable, Runnable {
|
||||
/** Constant <code>Blank</code>. */
|
||||
public final Command BLANK = new Command() {
|
||||
|
||||
private static final long serialVersionUID = 2689172297036001710L;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
@@ -1,71 +1,71 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constant interface.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: Constant.java 23713 2013-11-20 08:34:37Z Max mtg $
|
||||
*/
|
||||
public final class Constant {
|
||||
// used to pass information between the GUI screens
|
||||
/**
|
||||
* The Class Runtime.
|
||||
*/
|
||||
public static class Preferences {
|
||||
/** The Constant DevMode. */
|
||||
// one for normal mode, one for quest mode
|
||||
public static boolean DEV_MODE;
|
||||
/** The Constant UpldDrft. */
|
||||
public static boolean UPLOAD_DRAFT;
|
||||
|
||||
}
|
||||
|
||||
public static class Runtime {
|
||||
/** The Constant NetConn. */
|
||||
public static volatile boolean NET_CONN = false;
|
||||
|
||||
/** The Constant width. */
|
||||
public static final int WIDTH = 300;
|
||||
|
||||
/** The Constant height. */
|
||||
public static final int HEIGHT = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The Interface Keywords.
|
||||
*/
|
||||
public static class Keywords {
|
||||
|
||||
/** The loaded. */
|
||||
public static final boolean[] LOADED = { false };
|
||||
|
||||
/** The Non stacking list. */
|
||||
public static final List<String> NON_STACKING_LIST = new ArrayList<String>();
|
||||
}
|
||||
|
||||
} // Constant
|
||||
|
||||
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constant interface.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public final class Constant {
|
||||
// used to pass information between the GUI screens
|
||||
/**
|
||||
* The Class Runtime.
|
||||
*/
|
||||
public static class Preferences {
|
||||
/** The Constant DevMode. */
|
||||
// one for normal mode, one for quest mode
|
||||
public static boolean DEV_MODE;
|
||||
/** The Constant UpldDrft. */
|
||||
public static boolean UPLOAD_DRAFT;
|
||||
|
||||
}
|
||||
|
||||
public static class Runtime {
|
||||
/** The Constant NetConn. */
|
||||
public static volatile boolean NET_CONN = false;
|
||||
|
||||
/** The Constant width. */
|
||||
public static final int WIDTH = 300;
|
||||
|
||||
/** The Constant height. */
|
||||
public static final int HEIGHT = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The Interface Keywords.
|
||||
*/
|
||||
public static class Keywords {
|
||||
|
||||
/** The loaded. */
|
||||
public static final boolean[] LOADED = { false };
|
||||
|
||||
/** The Non stacking list. */
|
||||
public static final List<String> NON_STACKING_LIST = new ArrayList<String>();
|
||||
}
|
||||
|
||||
} // Constant
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ public class ImageCache {
|
||||
}
|
||||
return scaleImage(key, width, height, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* retrieve an image from the cache. returns null if the image is not found in the cache
|
||||
* and cannot be loaded from disk. pass -1 for width and/or height to avoid resizing in that dimension.
|
||||
@@ -250,12 +250,6 @@ public class ImageCache {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getTokenImageKey(String tokenName) {
|
||||
return TOKEN_PREFIX + tokenName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static String getImageLocator(PaperCard cp, boolean backFace, boolean includeSet, boolean isDownloadUrl) {
|
||||
final String nameToUse = getNameToUse(cp, backFace);
|
||||
if ( null == nameToUse )
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package forge;
|
||||
|
||||
import forge.item.InventoryItem;
|
||||
import forge.properties.NewConstants;
|
||||
|
||||
public class ImageCacheProvider implements ImageCacheBridge.Methods {
|
||||
|
||||
@Override
|
||||
public String getImageKey(InventoryItem cp, boolean altState) {
|
||||
return ImageCache.getImageKey(cp, altState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTokenKey(String imageName) {
|
||||
return ImageCache.getTokenImageKey(imageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMorphImage() {
|
||||
return NewConstants.CACHE_MORPH_IMAGE_FILE;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package forge;
|
||||
|
||||
import forge.PreferencesBridge.PreferencesSet;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
|
||||
public class PreferencesProvider implements PreferencesSet {
|
||||
@Override
|
||||
public boolean getEnableAiCheats() {
|
||||
return Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_ENABLE_AI_CHEATS);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getCloneModeSource() {
|
||||
return Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_CLONE_MODE_SOURCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogEntryType() {
|
||||
return Singletons.getModel().getPreferences().getPref(FPref.DEV_LOG_ENTRY_TYPE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getCurrentAiProfile() {
|
||||
return Singletons.getModel().getPreferences().getPref(FPref.UI_CURRENT_AI_PROFILE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRandomFoil() {
|
||||
return Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_RANDOM_FOIL);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isManaBurnEnabled() {
|
||||
// TODO Auto-generated method stub
|
||||
return Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_MANABURN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areBlocksFree() {
|
||||
return Singletons.getModel().getPreferences().getPrefBoolean(FPref.MATCHPREF_PROMPT_FREE_BLOCKS);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@ import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.card.MagicColor;
|
||||
import forge.card.mana.ManaAtom;
|
||||
import forge.card.mana.ManaCost;
|
||||
@@ -132,15 +133,15 @@ public class ComputerUtilMana {
|
||||
// select which abilities may be used for each shard
|
||||
MapOfLists<ManaCostShard, SpellAbility> sourcesForShards = ComputerUtilMana.groupAndOrderToPayShards(ai, manaAbilityMap, cost);
|
||||
|
||||
// if (DEBUG_MANA_PAYMENT) {
|
||||
// System.out.println((test ? "test -- " : "PROD -- ") + FThreads.debugGetStackTraceItem(5, true));
|
||||
// for (Entry<ManaCostShard, Collection<SpellAbility>> src : sourcesForShards.entrySet()) {
|
||||
// System.out.println("\t" +src.getKey() + " : " + src.getValue().size() + " source(s)");
|
||||
// for (SpellAbility sss : src.getValue()) {
|
||||
// System.out.printf("\t\t%s - %s%n", sss.getSourceCard(), sss);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (DEBUG_MANA_PAYMENT) {
|
||||
System.out.println((test ? "test -- " : "PROD -- ") + FThreads.debugGetStackTraceItem(5, true));
|
||||
for (Entry<ManaCostShard, Collection<SpellAbility>> src : sourcesForShards.entrySet()) {
|
||||
System.out.println("\t" +src.getKey() + " : " + src.getValue().size() + " source(s)");
|
||||
for (SpellAbility sss : src.getValue()) {
|
||||
System.out.printf("\t\t%s - %s%n", sss.getSourceCard(), sss);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<String> paymentPlan = new ArrayList<String>();
|
||||
|
||||
@@ -234,11 +235,11 @@ public class ComputerUtilMana {
|
||||
}
|
||||
handleOfferingsAI(sa, test, cost.isPaid());
|
||||
|
||||
// if (DEBUG_MANA_PAYMENT) {
|
||||
// System.err.printf("%s > [%s] payment has %s (%s +%d) for (%s) %s:%n\t%s%n%n",
|
||||
// FThreads.debugGetCurrThreadId(), test ? "test" : "PROD", cost.isPaid() ? "*PAID*" : "failed", originalCost,
|
||||
// extraMana, sa.getSourceCard(), sa.toUnsuppressedString(), StringUtils.join(paymentPlan, "\n\t"));
|
||||
// }
|
||||
if (DEBUG_MANA_PAYMENT) {
|
||||
System.err.printf("%s > [%s] payment has %s (%s +%d) for (%s) %s:%n\t%s%n%n",
|
||||
FThreads.debugGetCurrThreadId(), test ? "test" : "PROD", cost.isPaid() ? "*PAID*" : "failed", originalCost,
|
||||
extraMana, sa.getSourceCard(), sa.toUnsuppressedString(), StringUtils.join(paymentPlan, "\n\t"));
|
||||
}
|
||||
|
||||
if (!cost.isPaid()) {
|
||||
if (test) {
|
||||
@@ -1,80 +1,80 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AbilityFactory_Turns class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: AddTurnAi.java 23792 2013-11-24 10:02:58Z Max mtg $
|
||||
*/
|
||||
public class AddTurnAi extends SpellAbilityAi {
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||
final Player opp = ai.getWeakestOpponent();
|
||||
|
||||
if (sa.usesTargeting()) {
|
||||
sa.resetTargets();
|
||||
if (sa.canTarget(ai)) {
|
||||
sa.getTargets().add(ai);
|
||||
} else if (mandatory) {
|
||||
for (final Player ally : ai.getAllies()) {
|
||||
if (sa.canTarget(ally)) {
|
||||
sa.getTargets().add(ally);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sa.getTargetRestrictions().isMinTargetsChosen(sa.getSourceCard(), sa) && sa.canTarget(opp)) {
|
||||
sa.getTargets().add(opp);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final List<Player> tgtPlayers = AbilityUtils.getDefinedPlayers(sa.getSourceCard(), sa.getParam("Defined"), sa);
|
||||
for (final Player p : tgtPlayers) {
|
||||
if (p.isOpponentOf(ai) && !mandatory) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// not sure if the AI should be playing with cards that give the
|
||||
// Human more turns.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
|
||||
return doTriggerAINoCost(aiPlayer, sa, false);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AbilityFactory_Turns class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AddTurnAi extends SpellAbilityAi {
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||
final Player opp = ai.getWeakestOpponent();
|
||||
|
||||
if (sa.usesTargeting()) {
|
||||
sa.resetTargets();
|
||||
if (sa.canTarget(ai)) {
|
||||
sa.getTargets().add(ai);
|
||||
} else if (mandatory) {
|
||||
for (final Player ally : ai.getAllies()) {
|
||||
if (sa.canTarget(ally)) {
|
||||
sa.getTargets().add(ally);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sa.getTargetRestrictions().isMinTargetsChosen(sa.getSourceCard(), sa) && sa.canTarget(opp)) {
|
||||
sa.getTargets().add(opp);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final List<Player> tgtPlayers = AbilityUtils.getDefinedPlayers(sa.getSourceCard(), sa.getParam("Defined"), sa);
|
||||
for (final Player p : tgtPlayers) {
|
||||
if (p.isOpponentOf(ai) && !mandatory) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// not sure if the AI should be playing with cards that give the
|
||||
// Human more turns.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
|
||||
return doTriggerAINoCost(aiPlayer, sa, false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,109 +1,109 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AbilityFactory_Counters class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: CountersAi.java 23787 2013-11-24 07:09:23Z Max mtg $
|
||||
*/
|
||||
public abstract class CountersAi {
|
||||
// An AbilityFactory subclass for Putting or Removing Counters on Cards.
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* chooseCursedTarget.
|
||||
* </p>
|
||||
*
|
||||
* @param list
|
||||
* a {@link forge.CardList} object.
|
||||
* @param type
|
||||
* a {@link java.lang.String} object.
|
||||
* @param amount
|
||||
* a int.
|
||||
* @return a {@link forge.game.card.Card} object.
|
||||
*/
|
||||
public static Card chooseCursedTarget(final List<Card> list, final String type, final int amount) {
|
||||
Card choice;
|
||||
if (type.equals("M1M1")) {
|
||||
// try to kill the best killable creature, or reduce the best one
|
||||
final List<Card> killable = CardLists.filter(list, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return c.getNetDefense() <= amount;
|
||||
}
|
||||
});
|
||||
if (killable.size() > 0) {
|
||||
choice = ComputerUtilCard.getBestCreatureAI(killable);
|
||||
} else {
|
||||
choice = ComputerUtilCard.getBestCreatureAI(list);
|
||||
}
|
||||
} else {
|
||||
// improve random choice here
|
||||
choice = Aggregates.random(list);
|
||||
}
|
||||
return choice;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* chooseBoonTarget.
|
||||
* </p>
|
||||
*
|
||||
* @param list
|
||||
* a {@link forge.CardList} object.
|
||||
* @param type
|
||||
* a {@link java.lang.String} object.
|
||||
* @return a {@link forge.game.card.Card} object.
|
||||
*/
|
||||
public static Card chooseBoonTarget(final List<Card> list, final String type) {
|
||||
Card choice;
|
||||
if (type.equals("P1P1")) {
|
||||
choice = ComputerUtilCard.getBestCreatureAI(list);
|
||||
} else if (type.equals("DIVINITY")) {
|
||||
final List<Card> boon = CardLists.filter(list, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return c.getCounters(CounterType.DIVINITY) == 0;
|
||||
}
|
||||
});
|
||||
choice = ComputerUtilCard.getMostExpensivePermanentAI(boon, null, false);
|
||||
} else {
|
||||
// The AI really should put counters on cards that can use it.
|
||||
// Charge counters on things with Charge abilities, etc. Expand
|
||||
// these above
|
||||
choice = Aggregates.random(list);
|
||||
}
|
||||
return choice;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.ai.ability;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AbilityFactory_Counters class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class CountersAi {
|
||||
// An AbilityFactory subclass for Putting or Removing Counters on Cards.
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* chooseCursedTarget.
|
||||
* </p>
|
||||
*
|
||||
* @param list
|
||||
* a {@link forge.CardList} object.
|
||||
* @param type
|
||||
* a {@link java.lang.String} object.
|
||||
* @param amount
|
||||
* a int.
|
||||
* @return a {@link forge.game.card.Card} object.
|
||||
*/
|
||||
public static Card chooseCursedTarget(final List<Card> list, final String type, final int amount) {
|
||||
Card choice;
|
||||
if (type.equals("M1M1")) {
|
||||
// try to kill the best killable creature, or reduce the best one
|
||||
final List<Card> killable = CardLists.filter(list, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return c.getNetDefense() <= amount;
|
||||
}
|
||||
});
|
||||
if (killable.size() > 0) {
|
||||
choice = ComputerUtilCard.getBestCreatureAI(killable);
|
||||
} else {
|
||||
choice = ComputerUtilCard.getBestCreatureAI(list);
|
||||
}
|
||||
} else {
|
||||
// improve random choice here
|
||||
choice = Aggregates.random(list);
|
||||
}
|
||||
return choice;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* chooseBoonTarget.
|
||||
* </p>
|
||||
*
|
||||
* @param list
|
||||
* a {@link forge.CardList} object.
|
||||
* @param type
|
||||
* a {@link java.lang.String} object.
|
||||
* @return a {@link forge.game.card.Card} object.
|
||||
*/
|
||||
public static Card chooseBoonTarget(final List<Card> list, final String type) {
|
||||
Card choice;
|
||||
if (type.equals("P1P1")) {
|
||||
choice = ComputerUtilCard.getBestCreatureAI(list);
|
||||
} else if (type.equals("DIVINITY")) {
|
||||
final List<Card> boon = CardLists.filter(list, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return c.getCounters(CounterType.DIVINITY) == 0;
|
||||
}
|
||||
});
|
||||
choice = ComputerUtilCard.getMostExpensivePermanentAI(boon, null, false);
|
||||
} else {
|
||||
// The AI really should put counters on cards that can use it.
|
||||
// Charge counters on things with Charge abilities, etc. Expand
|
||||
// these above
|
||||
choice = Aggregates.random(list);
|
||||
}
|
||||
return choice;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,272 +1,272 @@
|
||||
/*
|
||||
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.ai.ability;
|
||||
|
||||
import forge.ai.AiCostDecision;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostDiscard;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.PaymentDecision;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class DrawAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
|
||||
return targetAI(ai, sa, false);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
final Card source = sa.getSourceCard();
|
||||
final Cost abCost = sa.getPayCosts();
|
||||
final Game game = ai.getGame();
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (!ComputerUtilCost.checkCreatureSacrificeCost(ai, abCost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
|
||||
AiCostDecision aiDecisions = new AiCostDecision(ai, sa);
|
||||
for (final CostPart part : abCost.getCostParts()) {
|
||||
if (part instanceof CostDiscard) {
|
||||
PaymentDecision decision = part.accept(aiDecisions);
|
||||
if ( null == decision )
|
||||
return false;
|
||||
for (Card discard : decision.cards) {
|
||||
if (!ComputerUtil.isWorseThanDraw(ai, discard)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkRemoveCounterCost(abCost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!targetAI(ai, sa, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tgt != null) {
|
||||
final Player player = sa.getTargets().getFirstTargetedPlayer();
|
||||
if (player != null && player.isOpponentOf(ai)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
if (ComputerUtil.preventRunAwayActivations(sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ComputerUtil.playImmediately(ai, sa)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Don't use draw abilities before main 2 if possible
|
||||
if (game.getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)
|
||||
&& !sa.hasParam("ActivationPhases") && !ComputerUtil.castSpellInMain1(ai, sa)) {
|
||||
return false;
|
||||
}
|
||||
if ((!game.getPhaseHandler().getNextTurn().equals(ai)
|
||||
|| game.getPhaseHandler().getPhase().isBefore(PhaseType.END_OF_TURN))
|
||||
&& !sa.hasParam("PlayerTurn") && !SpellAbilityAi.isSorcerySpeed(sa)
|
||||
&& ai.getCardsIn(ZoneType.Hand).size() > 1
|
||||
&& !ComputerUtil.activateForCost(sa, ai)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't tap creatures that may be able to block
|
||||
if (ComputerUtil.waitForBlocking(sa) && !sa.hasParam("ActivationPhases")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean targetAI(final Player ai, final SpellAbility sa, final boolean mandatory) {
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
final Card source = sa.getSourceCard();
|
||||
final boolean drawback = (sa instanceof AbilitySub);
|
||||
final Game game = ai.getGame();
|
||||
Player opp = ai.getOpponent();
|
||||
|
||||
int computerHandSize = ai.getCardsIn(ZoneType.Hand).size();
|
||||
final int humanLibrarySize = opp.getCardsIn(ZoneType.Library).size();
|
||||
final int computerLibrarySize = ai.getCardsIn(ZoneType.Library).size();
|
||||
final int computerMaxHandSize = ai.getMaxHandSize();
|
||||
|
||||
//if a spell is used don't count the card
|
||||
if (sa.isSpell() && source.isInZone(ZoneType.Hand)) {
|
||||
computerHandSize -= 1;
|
||||
}
|
||||
|
||||
int numCards = 1;
|
||||
if (sa.hasParam("NumCards")) {
|
||||
numCards = AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumCards"), sa);
|
||||
}
|
||||
|
||||
boolean xPaid = false;
|
||||
final String num = sa.getParam("NumCards");
|
||||
if ((num != null) && num.equals("X") && source.getSVar(num).equals("Count$xPaid")) {
|
||||
// Set PayX here to maximum value.
|
||||
if (sa instanceof AbilitySub && !source.getSVar("PayX").equals("")) {
|
||||
numCards = Integer.parseInt(source.getSVar("PayX"));
|
||||
} else {
|
||||
numCards = ComputerUtilMana.determineLeftoverMana(sa, ai);
|
||||
source.setSVar("PayX", Integer.toString(numCards));
|
||||
}
|
||||
xPaid = true;
|
||||
}
|
||||
//if (n)
|
||||
|
||||
// TODO: if xPaid and one of the below reasons would fail, instead of
|
||||
// bailing
|
||||
// reduce toPay amount to acceptable level
|
||||
|
||||
if (tgt != null) {
|
||||
// ability is targeted
|
||||
sa.resetTargets();
|
||||
|
||||
final boolean canTgtHuman = sa.canTarget(opp);
|
||||
final boolean canTgtComp = sa.canTarget(ai);
|
||||
boolean tgtHuman = false;
|
||||
|
||||
if (!canTgtHuman && !canTgtComp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (canTgtHuman && !opp.cantLose() && numCards >= humanLibrarySize) {
|
||||
// Deck the Human? DO IT!
|
||||
sa.getTargets().add(opp);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (numCards >= computerLibrarySize) {
|
||||
if (xPaid) {
|
||||
numCards = computerLibrarySize - 1;
|
||||
source.setSVar("PayX", Integer.toString(numCards));
|
||||
} else {
|
||||
// Don't deck your self
|
||||
if (!mandatory) {
|
||||
return false;
|
||||
}
|
||||
tgtHuman = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (computerHandSize + numCards > computerMaxHandSize && game.getPhaseHandler().isPlayerTurn(ai)) {
|
||||
if (xPaid) {
|
||||
numCards = computerMaxHandSize - computerHandSize;
|
||||
source.setSVar("PayX", Integer.toString(numCards));
|
||||
} else {
|
||||
// Don't draw too many cards and then risk discarding cards
|
||||
// at EOT
|
||||
// TODO: "NextUpkeep" is deprecated
|
||||
if (!(sa.hasParam("NextUpkeep") || (sa instanceof AbilitySub)) && !mandatory) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numCards == 0 && !mandatory && !drawback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!tgtHuman || !canTgtHuman) && canTgtComp) {
|
||||
sa.getTargets().add(ai);
|
||||
} else if (mandatory && canTgtHuman) {
|
||||
sa.getTargets().add(opp);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (!mandatory) {
|
||||
// TODO: consider if human is the defined player
|
||||
|
||||
// ability is not targeted
|
||||
if (numCards >= computerLibrarySize) {
|
||||
if (ai.isCardInPlay("Laboratory Maniac")) {
|
||||
return true;
|
||||
}
|
||||
// Don't deck yourself
|
||||
return false;
|
||||
}
|
||||
|
||||
if (numCards == 0 && !drawback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((computerHandSize + numCards > computerMaxHandSize)
|
||||
&& game.getPhaseHandler().isPlayerTurn(ai)
|
||||
&& !sa.isTrigger()) {
|
||||
// Don't draw too many cards and then risk discarding cards at
|
||||
// EOT
|
||||
if (!sa.hasParam("NextUpkeep") && !drawback) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} // drawTargetAI()
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||
return targetAI(ai, sa, mandatory);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.game.player.Player, forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
int numCards = sa.hasParam("NumCards") ? AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumCards"), sa) : 1;
|
||||
// AI shouldn't mill itself
|
||||
return numCards < player.getZone(ZoneType.Library).size();
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.ai.ability;
|
||||
|
||||
import forge.ai.AiCostDecision;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostDiscard;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.PaymentDecision;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
public class DrawAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
|
||||
return targetAI(ai, sa, false);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
protected boolean canPlayAI(Player ai, SpellAbility sa) {
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
final Card source = sa.getSourceCard();
|
||||
final Cost abCost = sa.getPayCosts();
|
||||
final Game game = ai.getGame();
|
||||
|
||||
if (abCost != null) {
|
||||
// AI currently disabled for these costs
|
||||
if (!ComputerUtilCost.checkCreatureSacrificeCost(ai, abCost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkLifeCost(ai, abCost, source, 4, null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) {
|
||||
AiCostDecision aiDecisions = new AiCostDecision(ai, sa);
|
||||
for (final CostPart part : abCost.getCostParts()) {
|
||||
if (part instanceof CostDiscard) {
|
||||
PaymentDecision decision = part.accept(aiDecisions);
|
||||
if ( null == decision )
|
||||
return false;
|
||||
for (Card discard : decision.cards) {
|
||||
if (!ComputerUtil.isWorseThanDraw(ai, discard)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkRemoveCounterCost(abCost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!targetAI(ai, sa, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tgt != null) {
|
||||
final Player player = sa.getTargets().getFirstTargetedPlayer();
|
||||
if (player != null && player.isOpponentOf(ai)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
if (ComputerUtil.preventRunAwayActivations(sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ComputerUtil.playImmediately(ai, sa)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Don't use draw abilities before main 2 if possible
|
||||
if (game.getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)
|
||||
&& !sa.hasParam("ActivationPhases") && !ComputerUtil.castSpellInMain1(ai, sa)) {
|
||||
return false;
|
||||
}
|
||||
if ((!game.getPhaseHandler().getNextTurn().equals(ai)
|
||||
|| game.getPhaseHandler().getPhase().isBefore(PhaseType.END_OF_TURN))
|
||||
&& !sa.hasParam("PlayerTurn") && !SpellAbilityAi.isSorcerySpeed(sa)
|
||||
&& ai.getCardsIn(ZoneType.Hand).size() > 1
|
||||
&& !ComputerUtil.activateForCost(sa, ai)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't tap creatures that may be able to block
|
||||
if (ComputerUtil.waitForBlocking(sa) && !sa.hasParam("ActivationPhases")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean targetAI(final Player ai, final SpellAbility sa, final boolean mandatory) {
|
||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||
final Card source = sa.getSourceCard();
|
||||
final boolean drawback = (sa instanceof AbilitySub);
|
||||
final Game game = ai.getGame();
|
||||
Player opp = ai.getOpponent();
|
||||
|
||||
int computerHandSize = ai.getCardsIn(ZoneType.Hand).size();
|
||||
final int humanLibrarySize = opp.getCardsIn(ZoneType.Library).size();
|
||||
final int computerLibrarySize = ai.getCardsIn(ZoneType.Library).size();
|
||||
final int computerMaxHandSize = ai.getMaxHandSize();
|
||||
|
||||
//if a spell is used don't count the card
|
||||
if (sa.isSpell() && source.isInZone(ZoneType.Hand)) {
|
||||
computerHandSize -= 1;
|
||||
}
|
||||
|
||||
int numCards = 1;
|
||||
if (sa.hasParam("NumCards")) {
|
||||
numCards = AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumCards"), sa);
|
||||
}
|
||||
|
||||
boolean xPaid = false;
|
||||
final String num = sa.getParam("NumCards");
|
||||
if ((num != null) && num.equals("X") && source.getSVar(num).equals("Count$xPaid")) {
|
||||
// Set PayX here to maximum value.
|
||||
if (sa instanceof AbilitySub && !source.getSVar("PayX").equals("")) {
|
||||
numCards = Integer.parseInt(source.getSVar("PayX"));
|
||||
} else {
|
||||
numCards = ComputerUtilMana.determineLeftoverMana(sa, ai);
|
||||
source.setSVar("PayX", Integer.toString(numCards));
|
||||
}
|
||||
xPaid = true;
|
||||
}
|
||||
//if (n)
|
||||
|
||||
// TODO: if xPaid and one of the below reasons would fail, instead of
|
||||
// bailing
|
||||
// reduce toPay amount to acceptable level
|
||||
|
||||
if (tgt != null) {
|
||||
// ability is targeted
|
||||
sa.resetTargets();
|
||||
|
||||
final boolean canTgtHuman = sa.canTarget(opp);
|
||||
final boolean canTgtComp = sa.canTarget(ai);
|
||||
boolean tgtHuman = false;
|
||||
|
||||
if (!canTgtHuman && !canTgtComp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (canTgtHuman && !opp.cantLose() && numCards >= humanLibrarySize) {
|
||||
// Deck the Human? DO IT!
|
||||
sa.getTargets().add(opp);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (numCards >= computerLibrarySize) {
|
||||
if (xPaid) {
|
||||
numCards = computerLibrarySize - 1;
|
||||
source.setSVar("PayX", Integer.toString(numCards));
|
||||
} else {
|
||||
// Don't deck your self
|
||||
if (!mandatory) {
|
||||
return false;
|
||||
}
|
||||
tgtHuman = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (computerHandSize + numCards > computerMaxHandSize && game.getPhaseHandler().isPlayerTurn(ai)) {
|
||||
if (xPaid) {
|
||||
numCards = computerMaxHandSize - computerHandSize;
|
||||
source.setSVar("PayX", Integer.toString(numCards));
|
||||
} else {
|
||||
// Don't draw too many cards and then risk discarding cards
|
||||
// at EOT
|
||||
// TODO: "NextUpkeep" is deprecated
|
||||
if (!(sa.hasParam("NextUpkeep") || (sa instanceof AbilitySub)) && !mandatory) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numCards == 0 && !mandatory && !drawback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((!tgtHuman || !canTgtHuman) && canTgtComp) {
|
||||
sa.getTargets().add(ai);
|
||||
} else if (mandatory && canTgtHuman) {
|
||||
sa.getTargets().add(opp);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (!mandatory) {
|
||||
// TODO: consider if human is the defined player
|
||||
|
||||
// ability is not targeted
|
||||
if (numCards >= computerLibrarySize) {
|
||||
if (ai.isCardInPlay("Laboratory Maniac")) {
|
||||
return true;
|
||||
}
|
||||
// Don't deck yourself
|
||||
return false;
|
||||
}
|
||||
|
||||
if (numCards == 0 && !drawback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((computerHandSize + numCards > computerMaxHandSize)
|
||||
&& game.getPhaseHandler().isPlayerTurn(ai)
|
||||
&& !sa.isTrigger()) {
|
||||
// Don't draw too many cards and then risk discarding cards at
|
||||
// EOT
|
||||
if (!sa.hasParam("NextUpkeep") && !drawback) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} // drawTargetAI()
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) {
|
||||
return targetAI(ai, sa, mandatory);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.game.player.Player, forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||
int numCards = sa.hasParam("NumCards") ? AbilityUtils.calculateAmount(sa.getSourceCard(), sa.getParam("NumCards"), sa) : 1;
|
||||
// AI shouldn't mill itself
|
||||
return numCards < player.getZone(ZoneType.Library).size();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user