- Laying some groundwork for DoTriggerAI() functions that will be used by the Trigger Controller instead of canPlayAI().

This commit is contained in:
jendave
2011-08-06 17:10:30 +00:00
parent 0276d69b17
commit 56b718bde5
22 changed files with 666 additions and 153 deletions

View File

@@ -17,7 +17,6 @@ public class AbilityFactory_AlterLife {
private static final long serialVersionUID = 8869422603616247307L;
final AbilityFactory af = AF;
final HashMap<String,String> params = af.getMapParams();
@Override
public String getStackDescription(){
@@ -32,13 +31,17 @@ public class AbilityFactory_AlterLife {
public boolean canPlayAI()
{
return gainLifeCanPlayAI(af, this, params.get("LifeAmount"));
return gainLifeCanPlayAI(af, this);
}
@Override
public void resolve() {
int amount = AbilityFactory.calculateAmount(af.getHostCard(), params.get("LifeAmount"), this);
gainLifeResolve(af, this, amount);
gainLifeResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return gainLifeDoTriggerAI(af, this, mandatory);
}
};
@@ -50,7 +53,6 @@ public class AbilityFactory_AlterLife {
private static final long serialVersionUID = 6631124959690157874L;
final AbilityFactory af = AF;
final HashMap<String,String> params = af.getMapParams();
@Override
public String getStackDescription(){
@@ -68,13 +70,12 @@ public class AbilityFactory_AlterLife {
// if X depends on abCost, the AI needs to choose which card he would sacrifice first
// then call xCount with that card to properly calculate the amount
// Or choosing how many to sacrifice
return gainLifeCanPlayAI(af, this, params.get("LifeAmount"));
return gainLifeCanPlayAI(af, this);
}
@Override
public void resolve() {
int amount = AbilityFactory.calculateAmount(af.getHostCard(), params.get("LifeAmount"), this);
gainLifeResolve(af, this, amount);
gainLifeResolve(af, this);
}
};
@@ -86,7 +87,6 @@ public class AbilityFactory_AlterLife {
private static final long serialVersionUID = 6631124959690157874L;
final AbilityFactory af = AF;
final HashMap<String,String> params = af.getMapParams();
@Override
public String getStackDescription(){
@@ -99,19 +99,23 @@ public class AbilityFactory_AlterLife {
// if X depends on abCost, the AI needs to choose which card he would sacrifice first
// then call xCount with that card to properly calculate the amount
// Or choosing how many to sacrifice
return gainLifeCanPlayAI(af, this, params.get("LifeAmount"));
return gainLifeCanPlayAI(af, this);
}
@Override
public void resolve() {
int amount = AbilityFactory.calculateAmount(af.getHostCard(), params.get("LifeAmount"), this);
gainLifeResolve(af, this, amount);
gainLifeResolve(af, this);
}
@Override
public boolean chkAI_Drawback() {
return true;
}
@Override
public boolean doTrigger(boolean mandatory) {
return gainLifeDoTriggerAI(af, this, mandatory);
}
};
return dbGainLife;
@@ -147,11 +151,12 @@ public class AbilityFactory_AlterLife {
return sb.toString();
}
public static boolean gainLifeCanPlayAI(final AbilityFactory af, final SpellAbility sa, final String amountStr){
public static boolean gainLifeCanPlayAI(final AbilityFactory af, final SpellAbility sa){
Random r = new Random();
Ability_Cost abCost = sa.getPayCosts();
final Card source = sa.getSourceCard();
int life = AllZone.ComputerPlayer.getLife();
String amountStr = af.getMapParams().get("LifeAmount");
if (abCost != null){
// AI currently disabled for these costs
@@ -184,32 +189,57 @@ public class AbilityFactory_AlterLife {
boolean chance = r.nextFloat() <= Math.pow(.6667, source.getAbilityUsed());
Target tgt = sa.getTarget();
if (sa.getTarget() != null){
if (tgt != null){
tgt.resetTargets();
sa.getTarget().addTarget(AllZone.ComputerPlayer);
if (tgt.canOnlyTgtOpponent())
tgt.addTarget(AllZone.HumanPlayer);
else
tgt.addTarget(AllZone.ComputerPlayer);
}
return ((r.nextFloat() < .6667) && chance);
}
public static void gainLifeResolve(final AbilityFactory af, final SpellAbility sa, int lifeAmount){
public static boolean gainLifeDoTriggerAI(AbilityFactory af, SpellAbility sa, boolean mandatory){
if (!ComputerUtil.canPayCost(sa) && !mandatory) // If there is a cost payment it's usually not mandatory
return false;
// If the Target is gaining life, target self.
// if the Target is modifying how much life is gained, this needs to be handled better
Target tgt = sa.getTarget();
if (tgt != null){
tgt.resetTargets();
if (tgt.canOnlyTgtOpponent())
tgt.addTarget(AllZone.HumanPlayer);
else
tgt.addTarget(AllZone.ComputerPlayer);
}
// check SubAbilities DoTrigger?
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
return abSub.doTrigger(mandatory);
}
return true;
}
public static void gainLifeResolve(final AbilityFactory af, final SpellAbility sa){
HashMap<String,String> params = af.getMapParams();
Card card = af.getHostCard();
int lifeAmount = AbilityFactory.calculateAmount(af.getHostCard(), params.get("LifeAmount"), sa);
ArrayList<Player> tgtPlayers;
Target tgt = af.getAbTgt();
if (tgt != null)
if (tgt != null && !params.containsKey("Defined"))
tgtPlayers = tgt.getTargetPlayers();
else
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), af.getMapParams().get("Defined"), sa);
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
for(Player p : tgtPlayers)
if (tgt == null || p.canTarget(af.getHostCard()))
p.gainLife(lifeAmount, sa.getSourceCard());
if (af.hasSubAbility()){
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null){
@@ -232,7 +262,6 @@ public class AbilityFactory_AlterLife {
private static final long serialVersionUID = 1129762905315395160L;
final AbilityFactory af = AF;
final HashMap<String,String> params = af.getMapParams();
@Override
public String getStackDescription(){
@@ -250,13 +279,17 @@ public class AbilityFactory_AlterLife {
// if X depends on abCost, the AI needs to choose which card he would sacrifice first
// then call xCount with that card to properly calculate the amount
// Or choosing how many to sacrifice
return loseLifeCanPlayAI(af, this, params.get("LifeAmount"));
return loseLifeCanPlayAI(af, this);
}
@Override
public void resolve() {
int amount = AbilityFactory.calculateAmount(af.getHostCard(), params.get("LifeAmount"), this);
loseLifeResolve(af, this, amount);
loseLifeResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return loseLifeDoTriggerAI(af, this, mandatory);
}
};
return abLoseLife;
@@ -267,7 +300,6 @@ public class AbilityFactory_AlterLife {
private static final long serialVersionUID = -2966932725306192437L;
final AbilityFactory af = AF;
final HashMap<String,String> params = af.getMapParams();
@Override
public String getStackDescription(){
@@ -285,13 +317,12 @@ public class AbilityFactory_AlterLife {
// if X depends on abCost, the AI needs to choose which card he would sacrifice first
// then call xCount with that card to properly calculate the amount
// Or choosing how many to sacrifice
return loseLifeCanPlayAI(af, this, params.get("LifeAmount"));
return loseLifeCanPlayAI(af, this);
}
@Override
public void resolve() {
int amount = AbilityFactory.calculateAmount(af.getHostCard(), params.get("LifeAmount"), this);
loseLifeResolve(af, this, amount);
loseLifeResolve(af, this);
}
};
return spLoseLife;
@@ -302,8 +333,7 @@ public class AbilityFactory_AlterLife {
private static final long serialVersionUID = -2966932725306192437L;
final AbilityFactory af = AF;
final HashMap<String,String> params = af.getMapParams();
@Override
public String getStackDescription(){
// when getStackDesc is called, just build exactly what is happening
@@ -315,19 +345,23 @@ public class AbilityFactory_AlterLife {
// if X depends on abCost, the AI needs to choose which card he would sacrifice first
// then call xCount with that card to properly calculate the amount
// Or choosing how many to sacrifice
return loseLifeCanPlayAI(af, this, params.get("LifeAmount"));
return loseLifeCanPlayAI(af, this);
}
@Override
public void resolve() {
int amount = AbilityFactory.calculateAmount(af.getHostCard(), params.get("LifeAmount"), this);
loseLifeResolve(af, this, amount);
loseLifeResolve(af, this);
}
@Override
public boolean chkAI_Drawback() {
return true;
}
@Override
public boolean doTrigger(boolean mandatory) {
return loseLifeDoTriggerAI(af, this, mandatory);
}
};
return dbLoseLife;
}
@@ -361,13 +395,15 @@ public class AbilityFactory_AlterLife {
return sb.toString();
}
public static boolean loseLifeCanPlayAI(final AbilityFactory af, final SpellAbility sa, final String amountStr){
public static boolean loseLifeCanPlayAI(final AbilityFactory af, final SpellAbility sa){
Random r = new Random();
Ability_Cost abCost = sa.getPayCosts();
final Card source = sa.getSourceCard();
int humanLife = AllZone.HumanPlayer.getLife();
int aiLife = AllZone.ComputerPlayer.getLife();
String amountStr = af.getMapParams().get("LifeAmount");
// TODO handle proper calculation of X values based on Cost and what would be paid
final int amount = AbilityFactory.calculateAmount(af.getHostCard(), amountStr, sa);
@@ -406,9 +442,28 @@ public class AbilityFactory_AlterLife {
return ((r.nextFloat() < .6667) && chance);
}
public static void loseLifeResolve(final AbilityFactory af, final SpellAbility sa, int lifeAmount){
public static boolean loseLifeDoTriggerAI(AbilityFactory af, SpellAbility sa, boolean mandatory){
if (!ComputerUtil.canPayCost(sa) && !mandatory) // If there is a cost payment it's usually not mandatory
return false;
Target tgt = sa.getTarget();
if (tgt != null){
tgt.addTarget(AllZone.HumanPlayer);
}
// check SubAbilities DoTrigger?
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
return abSub.doTrigger(mandatory);
}
return true;
}
public static void loseLifeResolve(final AbilityFactory af, final SpellAbility sa){
HashMap<String,String> params = af.getMapParams();
Card card = af.getHostCard();
int lifeAmount = AbilityFactory.calculateAmount(af.getHostCard(), params.get("LifeAmount"), sa);
ArrayList<Player> tgtPlayers;
@@ -477,6 +532,11 @@ public class AbilityFactory_AlterLife {
int amount = AbilityFactory.calculateAmount(af.getHostCard(), params.get("Num"), this);
poisonResolve(af, this, amount);
}
@Override
public boolean doTrigger(boolean mandatory) {
return poisonDoTriggerAI(af, this, mandatory);
}
};
return abPoison;
@@ -543,11 +603,41 @@ public class AbilityFactory_AlterLife {
public boolean chkAI_Drawback() {
return true;
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return poisonDoTriggerAI(af, this, mandatory);
}
};
return dbPoison;
}
public static boolean poisonDoTriggerAI(AbilityFactory af, SpellAbility sa, boolean mandatory){
if (!ComputerUtil.canPayCost(sa) && !mandatory) // If there is a cost payment it's usually not mandatory
return false;
Target tgt = sa.getTarget();
if (tgt != null){
tgt.addTarget(AllZone.HumanPlayer);
}
else{
ArrayList<Player> players = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), af.getMapParams().get("Defined"), sa);
for(Player p : players)
if (!mandatory && p.isComputer() && p.getPoisonCounters() > p.getOpponent().getPoisonCounters())
return false;
}
// check SubAbilities DoTrigger?
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
return abSub.doTrigger(mandatory);
}
return true;
}
private static void poisonResolve(final AbilityFactory af, final SpellAbility sa, int num){
HashMap<String,String> params = af.getMapParams();
Card card = af.getHostCard();

View File

@@ -30,6 +30,12 @@ public class AbilityFactory_ChangeZone {
return changeZoneDescription(AF, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
setMiscellaneous(AF, abChangeZone);
return abChangeZone;
@@ -75,6 +81,12 @@ public class AbilityFactory_ChangeZone {
public String getStackDescription(){
return changeZoneDescription(AF, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
setMiscellaneous(AF, dbChangeZone);
return dbChangeZone;
@@ -940,6 +952,12 @@ public class AbilityFactory_ChangeZone {
return changeZoneAllDescription(AF, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
setMiscellaneous(AF, abChangeZone);
return abChangeZone;
@@ -985,6 +1003,12 @@ public class AbilityFactory_ChangeZone {
public String getStackDescription(){
return changeZoneAllDescription(AF, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
setMiscellaneous(AF, dbChangeZone);
return dbChangeZone;

View File

@@ -28,6 +28,12 @@ public class AbilityFactory_Combat {
public void resolve() {
fogResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abFog;
@@ -74,6 +80,12 @@ public class AbilityFactory_Combat {
public boolean chkAI_Drawback() {
return fogPlayDrawbackAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbFog;
@@ -100,8 +112,11 @@ public class AbilityFactory_Combat {
public static boolean fogCanPlayAI(final AbilityFactory af, SpellAbility sa){
// AI should only activate this during Human's Declare Blockers phase
boolean chance = AllZone.Phase.is(Constant.Phase.Combat_Declare_Blockers_InstantAbility, sa.getActivatingPlayer().getOpponent());
boolean chance;
if (AllZone.Phase.isPlayerTurn(sa.getActivatingPlayer().getOpponent()))
chance = AllZone.Phase.isBefore(Constant.Phase.Combat_FirstStrikeDamage);
else
chance = AllZone.Phase.isAfter(Constant.Phase.Combat_Damage);
// Only cast when Stack is empty, so Human uses spells/abilities first
chance &= AllZone.Stack.size() == 0;
@@ -116,8 +131,11 @@ public class AbilityFactory_Combat {
public static boolean fogPlayDrawbackAI(final AbilityFactory af, SpellAbility sa){
// AI should only activate this during Human's turn
boolean chance = AllZone.Phase.isPlayerTurn(sa.getActivatingPlayer().getOpponent()) ||
AllZone.Phase.isAfter(Constant.Phase.Combat_Damage);
boolean chance;
if (AllZone.Phase.isPlayerTurn(sa.getActivatingPlayer().getOpponent()))
chance = AllZone.Phase.isBefore(Constant.Phase.Combat_FirstStrikeDamage);
else
chance = AllZone.Phase.isAfter(Constant.Phase.Combat_Damage);
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
@@ -126,6 +144,25 @@ public class AbilityFactory_Combat {
return chance;
}
public static boolean fogDoTriggerAI(AbilityFactory af, SpellAbility sa, boolean mandatory){
if (!ComputerUtil.canPayCost(sa) && !mandatory) // If there is a cost payment it's usually not mandatory
return false;
boolean chance;
if (AllZone.Phase.isPlayerTurn(sa.getActivatingPlayer().getOpponent()))
chance = AllZone.Phase.isBefore(Constant.Phase.Combat_FirstStrikeDamage);
else
chance = AllZone.Phase.isAfter(Constant.Phase.Combat_Damage);
// check SubAbilities DoTrigger?
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
return chance && abSub.doTrigger(mandatory);
}
return chance;
}
public static void fogResolve(final AbilityFactory af, final SpellAbility sa){
HashMap<String,String> params = af.getMapParams();
Card card = sa.getSourceCard();

View File

@@ -80,6 +80,12 @@ public class AbilityFactory_CounterMagic {
counterResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abCounter;
}

View File

@@ -34,6 +34,12 @@ public class AbilityFactory_Counters {
public void resolve() {
putResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abPutCounter;
@@ -87,6 +93,12 @@ public class AbilityFactory_Counters {
public boolean chkAI_Drawback() {
return putPlayDrawbackAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbPutCounter;
@@ -135,17 +147,17 @@ public class AbilityFactory_Counters {
Card choice = null;
String type = af.getMapParams().get("CounterType");
String amountStr = af.getMapParams().get("CounterNum");
Player player = af.isCurse() ? AllZone.HumanPlayer : AllZone.ComputerPlayer;
list = AllZoneUtil.getPlayerCardsInPlay(player);
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return CardFactoryUtil.canTarget(source, c);
}
});
if (abTgt != null){
list = list.getValidCards(abTgt.getValidTgts(),source.getController(),source);
@@ -158,7 +170,7 @@ public class AbilityFactory_Counters {
if (!pZone.getPlayer().equals(player))
return false;
}
if (abCost != null){
// AI currently disabled for these costs
if (abCost.getSacCost()){
@@ -166,7 +178,7 @@ public class AbilityFactory_Counters {
}
if (abCost.getLifeCost()) return false;
if (abCost.getDiscardCost()) return false;
if (abCost.getSubCounter()){
// A card has a 25% chance per counter to be able to pass through here
// 4+ counters will always pass. 0 counters will never
@@ -176,20 +188,20 @@ public class AbilityFactory_Counters {
return false;
}
}
if (!ComputerUtil.canPayCost(sa))
return false;
// TODO handle proper calculation of X values based on Cost
final int amount = AbilityFactory.calculateAmount(af.getHostCard(), amountStr, sa);
// prevent run-away activations - first time will always return true
boolean chance = r.nextFloat() <= Math.pow(.6667, source.getAbilityUsed());
// Targeting
if (abTgt != null){
abTgt.resetTargets();
// target loop
// prevent run-away activations - first time will always return true
boolean chance = r.nextFloat() <= Math.pow(.6667, source.getAbilityUsed());
// Targeting
if (abTgt != null){
abTgt.resetTargets();
// target loop
while(abTgt.getNumTargeted() < abTgt.getMaxTargets(sa.getSourceCard(), sa)){
if (list.size() == 0){
if (abTgt.getNumTargeted() < abTgt.getMinTargets(sa.getSourceCard(), sa) || abTgt.getNumTargeted() == 0){
@@ -201,38 +213,14 @@ public class AbilityFactory_Counters {
break;
}
}
if (af.isCurse()){
if (type.equals("M1M1")){
// try to kill the best killable creature, or reduce the best one
CardList killable = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.getNetDefense() <= amount;
}
});
if (killable.size() > 0)
choice = CardFactoryUtil.AI_getBestCreature(killable);
else
choice = CardFactoryUtil.AI_getBestCreature(list);
}
else{
// improve random choice here
list.shuffle();
choice = list.get(0);
}
}
else{
if (type.equals("P1P1")){
choice = CardFactoryUtil.AI_getBestCreature(list);
}
else{
// The AI really should put counters on cards that can use it.
// Charge counters on things with Charge abilities, etc. Expand these above
list.shuffle();
choice = list.get(0);
}
}
if (af.isCurse()){
choice = chooseCursedTarget(list, type, amount);
}
else{
choice = chooseBoonTarget(list, type, amount);
}
if (choice == null){ // can't find anything left
if (abTgt.getNumTargeted() < abTgt.getMinTargets(sa.getSourceCard(), sa) || abTgt.getNumTargeted() == 0){
abTgt.resetTargets();
@@ -246,21 +234,21 @@ public class AbilityFactory_Counters {
list.remove(choice);
abTgt.addTarget(choice);
}
}
else{
}
else{
// Placeholder: No targeting necessary
int currCounters = sa.getSourceCard().getCounters(Counters.valueOf(type));
int currCounters = sa.getSourceCard().getCounters(Counters.valueOf(type));
// each non +1/+1 counter on the card is a 10% chance of not activating this ability.
if (!type.equals("P1P1") && r.nextFloat() < .1 * currCounters)
return false;
}
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.chkAI_Drawback();
return ((r.nextFloat() < .6667) && chance);
if (!type.equals("P1P1") && r.nextFloat() < .1 * currCounters)
return false;
}
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.chkAI_Drawback();
return ((r.nextFloat() < .6667) && chance);
}
public static boolean putPlayDrawbackAI(final AbilityFactory af, final SpellAbility sa){
@@ -302,34 +290,10 @@ public class AbilityFactory_Counters {
}
if (af.isCurse()){
if (type.equals("M1M1")){
// try to kill the best killable creature, or reduce the best one
CardList killable = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.getNetDefense() <= amount;
}
});
if (killable.size() > 0)
choice = CardFactoryUtil.AI_getBestCreature(killable);
else
choice = CardFactoryUtil.AI_getBestCreature(list);
}
else{
// improve random choice here
list.shuffle();
choice = list.get(0);
}
choice = chooseCursedTarget(list, type, amount);
}
else{
if (type.equals("P1P1")){
choice = CardFactoryUtil.AI_getBestCreature(list);
}
else{
// The AI really should put counters on cards that can use it.
// Charge counters on things with Charge abilities, etc. Expand these above
list.shuffle();
choice = list.get(0);
}
}
if (choice == null){ // can't find anything left
@@ -354,6 +318,124 @@ public class AbilityFactory_Counters {
return chance;
}
public static boolean putDoTriggerAI(final AbilityFactory af, final SpellAbility sa, boolean mandatory){
// if there is a cost, it's gotta be optional
if (!ComputerUtil.canPayCost(sa) && !mandatory)
return false;
HashMap<String,String> params = af.getMapParams();
Target abTgt = sa.getTarget();
final Card source = sa.getSourceCard();
boolean chance = true;
boolean preferred = true;
CardList list;
Player player = af.isCurse() ? AllZone.HumanPlayer : AllZone.ComputerPlayer;
String type = af.getMapParams().get("CounterType");
String amountStr = af.getMapParams().get("CounterNum");
final int amount = AbilityFactory.calculateAmount(af.getHostCard(), amountStr, sa);
if (abTgt == null){
// No target. So must be defined
list = new CardList(AbilityFactory.getDefinedCards(source, params.get("Defined"), sa).toArray());
if (!mandatory){
// todo: If Trigger isn't mandatory, when wouldn't we want to put a counter?
// things like Powder Keg, which are way too complex for the AI
}
}
else{
list = AllZoneUtil.getPlayerCardsInPlay(player);
list = list.getTargetableCards(source);
if (abTgt != null){
list = list.getValidCards(abTgt.getValidTgts(),source.getController(),source);
}
if (list.isEmpty() && mandatory){
// If there isn't any prefered cards to target, gotta choose non-preferred ones
list = AllZoneUtil.getPlayerCardsInPlay(player.getOpponent());
list = list.getTargetableCards(source);
if (abTgt != null){
list = list.getValidCards(abTgt.getValidTgts(),source.getController(),source);
}
preferred = false;
}
// Not mandatory, or the the list was regenerated and is still empty, so return false since there are no targets
if (list.isEmpty())
return false;
Card choice = null;
// Choose targets here:
if (af.isCurse()){
if (preferred)
choice = chooseCursedTarget(list, type, amount);
else{
if (type.equals("M1M1")){
choice = CardFactoryUtil.AI_getWorstCreature(list);
}
else{
choice = CardFactoryUtil.getRandomCard(list);
}
}
}
else{
if (preferred)
choice = chooseBoonTarget(list, type, amount);
else{
if (type.equals("P1P1")){
choice = CardFactoryUtil.AI_getWorstCreature(list);
}
else{
choice = CardFactoryUtil.getRandomCard(list);
}
}
}
abTgt.addTarget(choice);
}
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.doTrigger(mandatory);
return true;
}
public static Card chooseCursedTarget(CardList list, String type, final int amount){
Card choice;
if (type.equals("M1M1")){
// try to kill the best killable creature, or reduce the best one
CardList killable = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return c.getNetDefense() <= amount;
}
});
if (killable.size() > 0)
choice = CardFactoryUtil.AI_getBestCreature(killable);
else
choice = CardFactoryUtil.AI_getBestCreature(list);
}
else{
// improve random choice here
choice = CardFactoryUtil.getRandomCard(list);
}
return choice;
}
public static Card chooseBoonTarget(CardList list, String type, final int amount){
Card choice;
if (type.equals("P1P1")){
choice = CardFactoryUtil.AI_getBestCreature(list);
}
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 = CardFactoryUtil.getRandomCard(list);
}
return choice;
}
public static void putResolve(final AbilityFactory af, final SpellAbility sa){
HashMap<String,String> params = af.getMapParams();
@@ -414,6 +496,12 @@ public class AbilityFactory_Counters {
public void resolve() {
removeResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abRemCounter;
@@ -467,6 +555,12 @@ public class AbilityFactory_Counters {
public boolean chkAI_Drawback() {
return removePlayDrawbackAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return spRemoveCounter;
@@ -656,6 +750,12 @@ public class AbilityFactory_Counters {
public String getStackDescription(){
return proliferateStackDescription(this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abProliferate;
@@ -713,6 +813,12 @@ public class AbilityFactory_Counters {
public boolean chkAI_Drawback() {
return shouldProliferateAI(this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbProliferate;
@@ -919,6 +1025,12 @@ public class AbilityFactory_Counters {
putAllResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abPutCounterAll;
}
@@ -967,6 +1079,12 @@ public class AbilityFactory_Counters {
return putAllPlayDrawbackAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbPutCounterAll;
}

View File

@@ -45,6 +45,12 @@ public class AbilityFactory_DealDamage {
AF.getHostCard().setAbilityUsed(AF.getHostCard().getAbilityUsed() + 1);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};// Ability_Activated
return abDamage;
@@ -77,6 +83,12 @@ public class AbilityFactory_DealDamage {
damageAllResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abDamageAll;
}
@@ -165,6 +177,12 @@ public class AbilityFactory_DealDamage {
doResolve(this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
}; // Drawback
return dbDealDamage;
@@ -191,6 +209,12 @@ public class AbilityFactory_DealDamage {
return true;
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbDamageAll;
}

View File

@@ -32,6 +32,12 @@ public class AbilityFactory_Destroy {
public void resolve() {
destroyResolve(af, this, noRegen);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abDestroy;
@@ -259,6 +265,12 @@ public class AbilityFactory_Destroy {
public void resolve() {
destroyAllResolve(af, this, noRegen);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abDestroyAll;
@@ -329,6 +341,12 @@ public class AbilityFactory_Destroy {
public boolean chkAI_Drawback() {
return true;
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbDestroyAll;

View File

@@ -121,6 +121,12 @@ public class AbilityFactory_GainControl {
}
return sb.toString();
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};//Ability_Activated
return abControl;

View File

@@ -22,6 +22,12 @@ public class AbilityFactory_Mana {
public void resolve() {
manaResolve(this, af);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abMana;
@@ -36,6 +42,12 @@ public class AbilityFactory_Mana {
Ability_Cost tmp = new Ability_Cost("0", AF.getHostCard().getName(), false);
Ability_Mana tmpMana = new Ability_Mana(AF.getHostCard(), tmp, produced){
private static final long serialVersionUID = 1454043766057140491L;
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
@@ -69,6 +81,12 @@ public class AbilityFactory_Mana {
Ability_Cost tmp = new Ability_Cost("0", AF.getHostCard().getName(), false);
Ability_Mana tmpMana = new Ability_Mana(AF.getHostCard(), tmp, produced){
private static final long serialVersionUID = 1454043766057140491L;
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
@@ -88,6 +106,12 @@ public class AbilityFactory_Mana {
// todo: AI shouldn't use this until he has a mana pool
return false;
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbMana;
@@ -198,6 +222,12 @@ public class AbilityFactory_Mana {
public void resolve() {
manaReflectedResolve(this, af);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
abMana.setReflectedMana(true);
@@ -215,6 +245,12 @@ public class AbilityFactory_Mana {
Ability_Mana tmpMana = new Ability_Mana(AF.getHostCard(), tmp, produced){
private static final long serialVersionUID = 1454043766057140491L;
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
// todo: maybe add can produce here, so old AI code can use reflected mana?
};
//tmpMana.setReflectedMana(true);

View File

@@ -28,6 +28,12 @@ public class AbilityFactory_PermanentState {
public void resolve() {
untapResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abUntap;
@@ -78,6 +84,12 @@ public class AbilityFactory_PermanentState {
public boolean chkAI_Drawback() {
return untapPlayDrawbackAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbUntap;
@@ -300,6 +312,12 @@ public class AbilityFactory_PermanentState {
public void resolve() {
tapResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abTap;
@@ -350,6 +368,12 @@ public class AbilityFactory_PermanentState {
public boolean chkAI_Drawback() {
return tapPlayDrawbackAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbTap;
@@ -572,6 +596,12 @@ public class AbilityFactory_PermanentState {
untapAllResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abUntap;
}
@@ -676,6 +706,12 @@ public class AbilityFactory_PermanentState {
tapAllResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abUntap;
}
@@ -723,6 +759,12 @@ public class AbilityFactory_PermanentState {
public boolean chkAI_Drawback() {
return tapAllPlayDrawbackAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbTap;

View File

@@ -87,6 +87,12 @@ public class AbilityFactory_Pump {
hostCard.setAbilityUsed(hostCard.getAbilityUsed() + 1);
}//resolve()
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};//SpellAbility
@@ -116,6 +122,12 @@ public class AbilityFactory_Pump {
public boolean chkAI_Drawback() {
return doDrawbackAI(this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};//SpellAbility
return dbPump;
@@ -512,6 +524,13 @@ public class AbilityFactory_Pump {
doPumpAllResolve(this);
hostCard.setAbilityUsed(hostCard.getAbilityUsed() + 1);
}//resolve()
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};//SpellAbility
@@ -630,6 +649,12 @@ public class AbilityFactory_Pump {
public boolean chkAI_Drawback() {
return chkPumpAllDrawbackAI(this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};//SpellAbility
return dbPumpAll;

View File

@@ -34,6 +34,12 @@ public class AbilityFactory_Regenerate {
public String getStackDescription(){
return regenerateStackDescription(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};//Ability_Activated

View File

@@ -27,6 +27,12 @@ public class AbilityFactory_Sacrifice {
public String getStackDescription(){
return sacrificeDescription(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abSacrifice;
}
@@ -73,6 +79,12 @@ public class AbilityFactory_Sacrifice {
public String getStackDescription(){
return sacrificeDescription(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbSacrifice;
}

View File

@@ -109,6 +109,12 @@ public class AbilityFactory_Token extends AbilityFactory {
public String getStackDescription() {
return doStackDescription(this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abToken;
@@ -164,6 +170,12 @@ public class AbilityFactory_Token extends AbilityFactory {
doResolve(this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
}; // Spell
return dbDealDamage;

View File

@@ -33,6 +33,12 @@ public class AbilityFactory_Turns {
int amount = AbilityFactory.calculateAmount(af.getHostCard(), params.get("NumTurns"), this);
addTurnResolve(af, this, amount);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abAddTurn;
@@ -97,6 +103,12 @@ public class AbilityFactory_Turns {
public boolean chkAI_Drawback() {
return true;
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbAddTurn;

View File

@@ -37,6 +37,12 @@ public class AbilityFactory_ZoneAffecting {
public void resolve() {
drawResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abDraw;
@@ -94,6 +100,12 @@ public class AbilityFactory_ZoneAffecting {
public boolean chkAI_Drawback() {
return drawTargetAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbDraw;
@@ -334,6 +346,12 @@ public class AbilityFactory_ZoneAffecting {
public void resolve() {
millResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abMill;
@@ -394,6 +412,12 @@ public class AbilityFactory_ZoneAffecting {
public boolean chkAI_Drawback() {
return millTargetAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbMill;
@@ -589,6 +613,12 @@ public class AbilityFactory_ZoneAffecting {
public void resolve() {
discardResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abDraw;
@@ -659,6 +689,12 @@ public class AbilityFactory_ZoneAffecting {
discardTargetAI(af);
return discardCheckDrawbackAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbDraw;
@@ -939,6 +975,12 @@ public class AbilityFactory_ZoneAffecting {
public boolean chkAI_Drawback() {
return scryTargetAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return dbScry;
@@ -1053,6 +1095,12 @@ public class AbilityFactory_ZoneAffecting {
public void resolve() {
scryResolve(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
// TODO Auto-generated method stub
return false;
}
};
return abScry;

View File

@@ -44,6 +44,10 @@ abstract public class Ability_Activated extends SpellAbility implements java.io.
return false;
return Cost_Payment.canPayAdditionalCosts(payCosts, this);
//TODO: make sure you can't play the Computer's activated abilities
}
// This should be overridden by ALL AFs
public boolean doTrigger(boolean mandatory){
return false;
}
}

View File

@@ -18,6 +18,8 @@ abstract public class Ability_Sub extends SpellAbility implements java.io.Serial
abstract public boolean chkAI_Drawback();
abstract public boolean doTrigger(boolean mandatory);
public void setParent(SpellAbility parent) {
this.parent = parent;
}

View File

@@ -3536,7 +3536,7 @@ public class GameActionUtil {
}
public static void showInfoDialg(String message) {
AllZone.Display.setCard(c);
//AllZone.Display.setCard(c); // c doesn't exist here!
JOptionPane.showMessageDialog(null, message);
}

View File

@@ -418,6 +418,10 @@ public class Phase extends MyObservable
public boolean isAfter(String phase) {
return phaseIndex > findIndex(phase);
}
public boolean isBefore(String phase) {
return phaseIndex < findIndex(phase);
}
private int findIndex(String phase) {
for(int i = 0; i < phaseOrder.length; i++) {

View File

@@ -68,7 +68,6 @@ public class PlayerZone_ComesIntoPlay extends DefaultPlayerZone {
AllZone.GameAction.checkWheneverKeyword(c,"EntersBattleField",null);
PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, c.getController());
PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, c.getController());
//Amulet of Vigor
if(c.isTapped()) {
@@ -99,7 +98,6 @@ public class PlayerZone_ComesIntoPlay extends DefaultPlayerZone {
//System.out.println("A land was just put onto the battlefield: " + c.getName());
CardList list = new CardList(play.getCards());
CardList graveList = new CardList(grave.getCards());
CardList listValakut = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
@@ -128,28 +126,6 @@ public class PlayerZone_ComesIntoPlay extends DefaultPlayerZone {
}
}
}
/*
CardList ankhs = AllZoneUtil.getCardsInPlay("Ankh of Mishra");
//
//ankhs.add(AllZoneUtil.getCardsInPlay("Zo-Zu the Punisher"));
//
final Card ankhLand = c;
for(Card ankh:ankhs) {
final Card source = ankh;
SpellAbility ability = new Ability(source, "") {
@Override
public void resolve() {
ankhLand.getController().addDamage(2, source);
}
};
StringBuilder sb = new StringBuilder();
sb.append(source).append(" - deals 2 damage to ").append(ankhLand.getController());
ability.setStackDescription(sb.toString());
AllZone.Stack.add(ability);
}
*/
CardList seeds = AllZoneUtil.getCardsInPlay("Seed the Land");
final Card seedLand = c;

View File

@@ -171,8 +171,19 @@ public class Target {
return sb.toString();
}
public boolean canOnlyTgtOpponent() {
boolean player = false;
boolean opponent = false;
for(String s: ValidTgts){
if (s.equals("Opponent"))
opponent = true;
else if (s.equals("Player"))
player = true;
}
return opponent && !player;
}
// These below functions are quite limited to the damage classes, we should find a way to move them into AF_DealDamage
public boolean canTgtPlayer() {
for(String s: ValidTgts){
if (s.equals("Player") || s.equals("Opponent"))