From d98a5fb291a7a56b00f303fc36903c15f8e53103 Mon Sep 17 00:00:00 2001 From: Hellfish Date: Mon, 13 Feb 2012 19:39:37 +0000 Subject: [PATCH] *Added AICheckSVar and AISVarCompare parameters to replacement effects to help the AI in deciding wether or not to apply a replacement effect. *Added AICheckSVar hints to Obstinate Familiar. *Added the ability to get at Replaced-variables the same way as triggered-variables. *Let ReplacementEffects be secondary (same as for triggers). --- res/cardsfolder/o/obstinate_familiar.txt | 4 +- src/main/java/forge/Card.java | 4 +- .../card/abilityfactory/AbilityFactory.java | 4 + .../card/replacement/ReplacementEffect.java | 43 +++++++++++ .../card/replacement/ReplacementHandler.java | 75 +++++++++++-------- 5 files changed, 96 insertions(+), 34 deletions(-) diff --git a/res/cardsfolder/o/obstinate_familiar.txt b/res/cardsfolder/o/obstinate_familiar.txt index 6f9cbc2df1b..afd6abc020b 100644 --- a/res/cardsfolder/o/obstinate_familiar.txt +++ b/res/cardsfolder/o/obstinate_familiar.txt @@ -3,8 +3,8 @@ ManaCost:R Types:Creature Human Wizard Text:no text PT:1/1 -R:Event$ Draw | ValidPlayer$ You | Optional$ True | Prevent$ True | Description$ If you would draw a card, you may skip that draw instead. -SVar:RemAIDeck:True +R:Event$ Draw | ValidPlayer$ You | Optional$ True | Prevent$ True | AICheckSVar$ AIHandling | AISVarCompare$ EQ0 | Description$ If you would draw a card, you may skip that draw instead. +SVar:AIHandling:Count$InYourLibrary Oracle:If you would draw a card, you may skip that draw instead. SetInfo:ODY|Rare|http://magiccards.info/scans/en/od/210.jpg End \ No newline at end of file diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index 64f353ad100..b659a354957 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -2581,7 +2581,9 @@ public class Card extends GameEntity implements Comparable { // Replacement effects for (final ReplacementEffect replacementEffect : this.getCharacteristics().getReplacementEffects()) { - sb.append(replacementEffect.toString() + "\r\n"); + if(!replacementEffect.isSecondary()) { + sb.append(replacementEffect.toString() + "\r\n"); + } } // static abilities diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactory.java b/src/main/java/forge/card/abilityfactory/AbilityFactory.java index 798dc32f0f0..d070653952e 100644 --- a/src/main/java/forge/card/abilityfactory/AbilityFactory.java +++ b/src/main/java/forge/card/abilityfactory/AbilityFactory.java @@ -1653,6 +1653,10 @@ public class AbilityFactory { final int count = (Integer) root.getTriggeringObject(l[0]); return CardFactoryUtil.doXMath(count, m, card) * multiplier; + } else if (calcX[0].startsWith("Replaced")) { + final SpellAbility root = ability.getRootSpellAbility(); + list = new CardList(); + list.add((Card) root.getReplacingObject(calcX[0].substring(8))); } else if (calcX[0].startsWith("ReplaceCount")) { // ReplaceCount is similar to a regular Count, but just // pulls Integer Values from Replacement objects diff --git a/src/main/java/forge/card/replacement/ReplacementEffect.java b/src/main/java/forge/card/replacement/ReplacementEffect.java index ab9df4df128..03647667cb3 100644 --- a/src/main/java/forge/card/replacement/ReplacementEffect.java +++ b/src/main/java/forge/card/replacement/ReplacementEffect.java @@ -46,6 +46,49 @@ public abstract class ReplacementEffect extends TriggerReplacementBase { public final boolean hasRun() { return hasRun; } + + public final boolean isSecondary() { + return mapParams.containsKey("Secondary"); + } + + public final boolean aiShouldRun(final SpellAbility sa) { + if(mapParams.containsKey("AICheckSVar")) { + String svarToCheck = mapParams.get("AICheckSVar"); + String comparator = "GE"; + int compareTo = 1; + + if(mapParams.containsKey("AISVarCompare")) { + String fullCmp = mapParams.get("AISVarCompare"); + comparator = fullCmp.substring(0,2); + String strCmpTo = fullCmp.substring(2); + try { + compareTo = Integer.parseInt(strCmpTo); + } + catch(Exception ignored) { + if(sa == null) { + compareTo = CardFactoryUtil.xCount(hostCard, hostCard.getSVar(strCmpTo)); + } else { + compareTo = AbilityFactory.calculateAmount(hostCard, hostCard.getSVar(strCmpTo), sa); + } + } + } + + int left = 0; + + if(sa == null) { + left = CardFactoryUtil.xCount(hostCard, hostCard.getSVar(svarToCheck)); + } else { + left = AbilityFactory.calculateAmount(hostCard, hostCard.getSVar(svarToCheck), sa); + } + + if(AllZoneUtil.compare(left, comparator, compareTo)) { + return true; + } + + } + + return false; + } /** * Sets the checks for run. diff --git a/src/main/java/forge/card/replacement/ReplacementHandler.java b/src/main/java/forge/card/replacement/ReplacementHandler.java index ddaa6208058..8fed78f461c 100644 --- a/src/main/java/forge/card/replacement/ReplacementHandler.java +++ b/src/main/java/forge/card/replacement/ReplacementHandler.java @@ -98,25 +98,8 @@ public class ReplacementHandler { } } - if (chosenRE != null) { - //Player optDecider = decider; - //optDecider = AbilityFactory.getDefinedPlayers(chosenRE.getHostCard(), chosenRE.getMapParams().get("OptionalDecider"), null).get(0); - if (chosenRE.getMapParams().containsKey("Optional")) { - if (decider.isHuman()) { - StringBuilder buildQuestion = new StringBuilder("Apply replacement effect of "); - buildQuestion.append(chosenRE.getHostCard()); - buildQuestion.append("?\r\n("); - buildQuestion.append(chosenRE.toString()); - buildQuestion.append(")"); - if (!GameActionUtil.showYesNoDialog(chosenRE.getHostCard(), buildQuestion.toString())) { - return false; - } - } else { - //AI-logic for deciding whether or not to apply the optional replacement effect happens here. - } - } - executeReplacement(runParams, chosenRE); - return true; + if (chosenRE != null) { + return executeReplacement(runParams, chosenRE, decider); } else { return false; } @@ -128,26 +111,54 @@ public class ReplacementHandler { * Runs a single replacement effect. * @param replacementEffect the replacement effect to run */ - private void executeReplacement(HashMap runParams, ReplacementEffect replacementEffect) { + private boolean executeReplacement(HashMap runParams, ReplacementEffect replacementEffect, Player decider) { HashMap mapParams = replacementEffect.getMapParams(); replacementEffect.setHasRun(true); + + SpellAbility effectSA = null; + + if(mapParams.containsKey("ReplaceWith")) { + String effectSVar = mapParams.get("ReplaceWith"); + String effectAbString = replacementEffect.getHostCard().getSVar(effectSVar); + + AbilityFactory abilityFactory = new AbilityFactory(); + + effectSA = abilityFactory.getAbility(effectAbString, replacementEffect.getHostCard()); + + replacementEffect.setReplacingObjects(runParams, effectSA); + } + + //Decider gets to choose wether or not to apply the replacement. + if (replacementEffect.getMapParams().containsKey("Optional")) { + Player optDecider = decider; + if(mapParams.containsKey("OptionalDecider") && effectSA != null) { + optDecider = AbilityFactory.getDefinedPlayers(replacementEffect.getHostCard(), mapParams.get("OptionalDecider"), effectSA).get(0); + } + + if (optDecider.isHuman()) { + StringBuilder buildQuestion = new StringBuilder("Apply replacement effect of "); + buildQuestion.append(replacementEffect.getHostCard()); + buildQuestion.append("?\r\n("); + buildQuestion.append(replacementEffect.toString()); + buildQuestion.append(")"); + if (!GameActionUtil.showYesNoDialog(replacementEffect.getHostCard(), buildQuestion.toString())) { + return false; + } + } else { + //AI-logic + if(!replacementEffect.aiShouldRun(effectSA)) { + return false; + } + } + } if (mapParams.containsKey("Prevent")) { if (mapParams.get("Prevent").equals("True")) { replacementEffect.setHasRun(false); - return; //Nothing should replace the event. + return true; //Nothing should replace the event. } - } - - String effectSVar = mapParams.get("ReplaceWith"); - String effectAbString = replacementEffect.getHostCard().getSVar(effectSVar); - - AbilityFactory abilityFactory = new AbilityFactory(); - - SpellAbility effectSA = abilityFactory.getAbility(effectAbString, replacementEffect.getHostCard()); - - replacementEffect.setReplacingObjects(runParams, effectSA); + } if (replacementEffect.getHostCard().getController().isHuman()) { AllZone.getGameAction().playSpellAbilityNoStack(effectSA, false); @@ -157,6 +168,8 @@ public class ReplacementHandler { } replacementEffect.setHasRun(false); + + return true; } /**