- Initial code for AF_ChangeZone, a more generalized version of Bounce, Retrieve and Fetch.

- Converted AEther Vial, Boomerang, Brainstorm, Buried Alive, Elvish Piper, Fertilid, Jester's Cap, Raise Dead to AF_ChangeZone
This commit is contained in:
jendave
2011-08-06 13:31:49 +00:00
parent 52daae99fb
commit a35bd26c4e
14 changed files with 897 additions and 171 deletions

1
.gitattributes vendored
View File

@@ -6033,6 +6033,7 @@ src/forge/Ability.java svneol=native#text/plain
src/forge/AbilityFactory.java -text svneol=native#text/plain
src/forge/AbilityFactory_AlterLife.java -text svneol=native#text/plain
src/forge/AbilityFactory_Bounce.java -text svneol=native#text/plain
src/forge/AbilityFactory_ChangeZone.java -text svneol=native#text/plain
src/forge/AbilityFactory_Combat.java -text svneol=native#text/plain
src/forge/AbilityFactory_CounterMagic.java -text svneol=native#text/plain
src/forge/AbilityFactory_Counters.java -text svneol=native#text/plain

View File

@@ -2,7 +2,9 @@ Name:AEther Vial
ManaCost:1
Types:Artifact
Text:no text
A:AB$ChangeZone | Cost$ T | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature.cmcEQX | ChangeNum$ 1 | SpellDescription$ You may put a creature card with converted mana cost equal to the number of charge counters on <20>ther Vial from your hand onto the battlefield.
K:WheneverKeyword:BeginningOfUpkeep:No_Initiator:Play:CustomCounter.CHARGE/1:Self:ASAP:Yes_No:ControllerUpkeep:At the beginning of your upkeep, you may put a charge counter on CARDNAME.
SVar:X:Count$CardCounters.CHARGE
SVar:RemAIDeck:True
SVar:Rarity:Uncommon
SVar:Picture:http://www.wizards.com/global/images/magic/general/aether_vial.jpg

View File

@@ -2,7 +2,7 @@ Name:Boomerang
ManaCost:U U
Types:Instant
Text:no text
A:SP$Bounce | Cost$ U U | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | Destination$ Hand | SpellDescription$ Return target permanent to its owner's hand.
A:SP$ChangeZone | Cost$ U U | ValidTgts$ Permanent | TgtPrompt$ Select target permanent | Origin$ Battlefield | Destination$ Hand | SpellDescription$ Return target permanent to its owner's hand.
SVar:Rarity:Common
SVar:Picture:http://www.wizards.com/global/images/magic/general/boomerang.jpg
SetInfo:8ED|Common|http://magiccards.info/scans/en/8e/63.jpg

View File

@@ -2,7 +2,8 @@ Name:Brainstorm
ManaCost:U
Types:Instant
Text:no text
A:SP$Draw | Cost$ U | NumCards$ 3 | SpellDescription$ Draw three cards, then put two cards from your hand on top of your library in any order. | SubAbility$ YouHandToLibrary/2/Top
A:SP$Draw | Cost$ U | NumCards$ 3 | SpellDescription$ Draw three cards, then put two cards from your hand on top of your library in any order. | SubAbility$ SVar=ChangeZoneDB
SVar:ChangeZoneDB:DB$ChangeZone | Origin$ Hand | Destination$ Library | ChangeNum$ 2
SVar:Rarity:Common
SVar:Picture:http://www.wizards.com/global/images/magic/general/brainstorm.jpg
SetInfo:5ED|Common|http://magiccards.info/scans/en/5e/76.jpg

View File

@@ -1,7 +1,8 @@
Name:Buried Alive
ManaCost:2 B
Types:Sorcery
Text:Search your library for up to three creature cards and put them into your graveyard. Then shuffle your library.
Text:no text
A:SP$ChangeZone | Cost$ 2 B | Origin$ Library | Destination$ Graveyard | ChangeType$ Creature | ChangeNum$ 3 | SpellDescription$ Search your library for up to three creature cards and put them into your graveyard. Then shuffle your library.
SVar:Rarity:Uncommon
SVar:Picture:http://www.wizards.com/global/images/magic/general/buried_alive.jpg
SetInfo:WTH|Uncommon|http://magiccards.info/scans/en/wl/5.jpg

View File

@@ -1,7 +1,8 @@
Name:Elvish Piper
ManaCost:3 G
Types:Creature Elf Shaman
Text:G, tap: You may put a creature card from your hand onto the battlefield.
Text:no text
A:AB$ChangeZone | Cost$ G T | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature | ChangeNum$ 1 | SpellDescription$ You may put a creature card from your hand onto the battlefield.
PT:1/1
SVar:Rarity:Rare
SVar:Picture:http://resources.wizards.com/magic/cards/9ed/en-us/card83072.jpg

View File

@@ -4,7 +4,7 @@ Types:Creature Elemental
Text:no text
PT:0/0
K:etbCounter:P1P1:2
A:AB$Fetch | Cost$ 1 G SubCounter<1/P1P1> | ValidTgts$Player | Destination$ Battlefield | Tapped$ True | FetchType$ Land.Basic | FetchNum$ 1 | SpellDescription$ Target player searches his or her library for a basic land card and puts it onto the battlefield tapped. Then that player shuffles his or her library.
A:AB$ChangeZone | Cost$ 1 G SubCounter<1/P1P1> | ValidTgts$ Player | Defined$ Targeted | Origin$ Library | Destination$ Battlefield | Tapped$ True | ChangeType$ Land.Basic | ChangeNum$ 1 | SpellDescription$ Target player searches his or her library for a basic land card and puts it onto the battlefield tapped. Then that player shuffles his or her library.
SVar:Rarity:Common
SVar:Picture:http://www.wizards.com/global/images/magic/general/fertilid.jpg
SetInfo:MOR|Common|http://magiccards.info/scans/en/mt/122.jpg

View File

@@ -1,7 +1,8 @@
Name:Jester's Cap
ManaCost:4
Types:Artifact
Text:2, Tap, Sacrifice Jester's Cap: Search target player's library for three cards and exile them. Then that player shuffles his or her library.
Text:no text
A:AB$ChangeZone | Cost$ 2 T Sac<1/CARDNAME> | ValidTgts$ Player | Origin$ Library | Destination$ Exile | ChangeType$ Card | ChangeNum$ 3 | IsCurse$ True | SpellDescription$ Search target player's library for three cards and exile them. Then that player shuffles his or her library.
SVar:RemAIDeck:True
SVar:Rarity:Rare
SVar:Picture:http://www.wizards.com/global/images/magic/general/jesters_cap.jpg

View File

@@ -2,7 +2,7 @@ Name:Raise Dead
ManaCost:B
Types:Sorcery
Text:no text
A:SP$Retrieve | Cost$ B | Destination$ Hand | TgtPrompt$ Choose target creature card in your graveyard | ValidTgts$ Creature.YouCtrl | SpellDescription$ Return target creature card from your graveyard to your hand.
A:SP$ChangeZone | Cost$ B | Origin$ Graveyard | Destination$ Hand | TgtPrompt$ Choose target creature card in your graveyard | ValidTgts$ Creature.YouCtrl | SpellDescription$ Return target creature card from your graveyard to your hand.
SVar:Rarity:Common
SVar:Picture:http://resources.wizards.com/magic/cards/9ed/en-us/card83220.jpg
SetInfo:8ED|Common|http://magiccards.info/scans/en/8e/157.jpg

View File

@@ -217,7 +217,17 @@ public class AbilityFactory {
SA = AbilityFactory_Counters.createDrawbackProliferate(this);
}
// do we want to merge Fetch, Retrieve and Bounce into ChangeZone?
if (API.equals("ChangeZone")){
if (isAb)
SA = AbilityFactory_ChangeZone.createAbilityChangeZone(this);
else if (isSp)
SA = AbilityFactory_ChangeZone.createSpellChangeZone(this);
else if (isDb)
SA = AbilityFactory_ChangeZone.createDrawbackChangeZone(this);
}
// Fetch, Retrieve and Bounce should be converted ChangeZone
if (API.equals("Fetch")){
if (isAb)
SA = AbilityFactory_Fetch.createAbilityFetch(this);
@@ -239,7 +249,7 @@ public class AbilityFactory {
SA = AbilityFactory_Bounce.createSpellBounce(this);
hostCard.setSVar("PlayMain1", "TRUE");
}
// Above to be merged? If so, merge then do SubAbility for each
// Convert above abilities to gain Drawback
if (API.equals("Pump"))
{
@@ -607,6 +617,12 @@ public class AbilityFactory {
players = new ArrayList<Player>();
if (defined.equals("Targeted")){
Target tgt = sa.getTarget();
if (tgt != null && tgt.getTargetPlayers().size() != 0){
players.addAll(tgt.getTargetPlayers());
return players;
}
SpellAbility parent;
do{
parent = ((Ability_Sub)sa).getParent();
@@ -630,6 +646,12 @@ public class AbilityFactory {
objects = new ArrayList<Object>();
if (defined.equals("Targeted")){
Target tgt = sa.getTarget();
if (tgt != null && tgt.getTargets().size() != 0){
objects.addAll(tgt.getTargets());
return objects;
}
SpellAbility parent;
do{
parent = ((Ability_Sub)sa).getParent();

View File

@@ -0,0 +1,854 @@
package forge;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
public class AbilityFactory_ChangeZone {
// Change Zone is going to work much differently than other AFs.
// *NOTE* Please do not use this as a base for copying and creating your own AF
public static SpellAbility createAbilityChangeZone(final AbilityFactory AF){
final SpellAbility abChangeZone = new Ability_Activated(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()){
private static final long serialVersionUID = 3728332812890211671L;
public boolean canPlayAI(){
return changeZoneCanPlayAI(AF, this);
}
@Override
public void resolve() {
changeZoneResolve(AF, this);
}
@Override
public String getStackDescription(){
return changeZoneDescription(AF, this);
}
};
setMiscellaneous(AF, abChangeZone);
return abChangeZone;
}
public static SpellAbility createSpellChangeZone(final AbilityFactory AF){
final SpellAbility spChangeZone = new Spell(AF.getHostCard(), AF.getAbCost(), AF.getAbTgt()) {
private static final long serialVersionUID = 3270484211099902059L;
public boolean canPlayAI(){
return changeZoneCanPlayAI(AF, this);
}
@Override
public void resolve() {
changeZoneResolve(AF, this);
}
@Override
public String getStackDescription(){
return changeZoneDescription(AF, this);
}
};
setMiscellaneous(AF, spChangeZone);
return spChangeZone;
}
public static SpellAbility createDrawbackChangeZone(final AbilityFactory AF){
final SpellAbility dbChangeZone = new Ability_Sub(AF.getHostCard(), AF.getAbTgt()) {
private static final long serialVersionUID = 3270484211099902059L;
@Override
public void resolve() {
changeZoneResolve(AF, this);
}
@Override
public boolean chkAI_Drawback() {
return changeZonePlayDrawbackAI(AF, this);
}
@Override
public String getStackDescription(){
return changeZoneDescription(AF, this);
}
};
setMiscellaneous(AF, dbChangeZone);
return dbChangeZone;
}
private static void setMiscellaneous(AbilityFactory af, SpellAbility sa){
// todo: if moving to or from Battlefield allow use in Main1?
HashMap<String,String> params = af.getMapParams();
if (af.getAbTgt() != null)
af.getAbTgt().setZone(params.get("Origin"));
if (!(sa instanceof Ability_Sub))
if (params.get("Origin").equals("Battlefield") || params.get("Destination").equals("Battlefield"))
af.getHostCard().setSVar("PlayMain1", "TRUE");
}
private static boolean changeZoneCanPlayAI(AbilityFactory af, SpellAbility sa){
HashMap<String,String> params = af.getMapParams();
String origin = params.get("Origin");
if (origin.equals("Library") || origin.equals("Hand") || origin.equals("Sideboard")){
return changeHiddenOriginCanPlayAI(af, sa);
}
else if (origin.equals("Graveyard") || origin.equals("Exile") || origin.equals("Battlefield")){
return changeKnownOriginCanPlayAI(af, sa);
}
return false;
}
private static boolean changeZonePlayDrawbackAI(AbilityFactory af, SpellAbility sa){
HashMap<String,String> params = af.getMapParams();
String origin = params.get("Origin");
if (origin.equals("Library") || origin.equals("Hand") || origin.equals("Sideboard")){
return changeHiddenOriginPlayDrawbackAI(af, sa);
}
else if (origin.equals("Graveyard") || origin.equals("Exile") || origin.equals("Battlefield")){
return changeKnownOriginPlayDrawbackAI(af, sa);
}
return false;
}
private static String changeZoneDescription(AbilityFactory af, SpellAbility sa){
HashMap<String,String> params = af.getMapParams();
String origin = params.get("Origin");
if (origin.equals("Library") || origin.equals("Hand") || origin.equals("Sideboard")){
return changeHiddenOriginStackDescription(af, sa);
}
else if (origin.equals("Graveyard") || origin.equals("Exile") || origin.equals("Battlefield")){
return changeKnownOriginStackDescription(af, sa);
}
return "";
}
private static void changeZoneResolve(AbilityFactory af, SpellAbility sa){
HashMap<String,String> params = af.getMapParams();
String origin = params.get("Origin");
if (origin.equals("Library") || origin.equals("Hand") || origin.equals("Sideboard")){
changeHiddenOriginResolve(af, sa);
}
else if (origin.equals("Graveyard") || origin.equals("Exile") || origin.equals("Battlefield")){
changeKnownOriginResolve(af, sa);
}
}
// *************************************************************************************
// ************ Hidden Origin (Library/Hand/Sideboard) *********************************
// ******* Hidden origin cards are chosen on the resolution of the spell ***************
// *************************************************************************************
private static boolean changeHiddenOriginCanPlayAI(AbilityFactory af, SpellAbility sa){
// Fetching should occur fairly often as it helps cast more spells, and have access to more mana
Ability_Cost abCost = af.getAbCost();
Card source = af.getHostCard();
HashMap<String,String> params = af.getMapParams();
//String destination = params.get("Destination");
String origin = params.get("Origin");
if (abCost != null){
// AI currently disabled for these costs
if (abCost.getSacCost()){
// Sac is ok in general, but should add some decision making based off what we Sacrifice and what we might get
}
if (abCost.getLifeCost()){
if (AllZone.ComputerPlayer.getLife() - abCost.getLifeAmount() < 4)
return false;
}
if (abCost.getDiscardCost()) return false;
if (abCost.getSubCounter()) return true; // only card that uses it is Fertilid
}
if (!ComputerUtil.canPayCost(sa))
return false;
Random r = new Random();
// prevent run-away activations - first time will always return true
boolean chance = r.nextFloat() <= Math.pow(.6667, source.getAbilityUsed());
ArrayList<Player> pDefined;
Target tgt = af.getAbTgt();
if(tgt != null && tgt.canTgtPlayer()) {
if (af.isCurse())
tgt.addTarget(AllZone.HumanPlayer);
else
tgt.addTarget(AllZone.ComputerPlayer);
pDefined = tgt.getTargetPlayers();
}
else{
pDefined = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
}
for(Player p : pDefined){
if (origin.equals("Hand")){
CardList hand = AllZoneUtil.getPlayerHand(p);
if (hand.size() == 0)
return false;
if (p.isComputer()){
if (params.containsKey("ChangeType")){
hand = filterListByType(hand, params, "ChangeType", sa);
if (hand.size() == 0)
return false;
}
}
// TODO: add some more improvements based on Destination and Type
}
else if (origin.equals("Library")){
CardList library = AllZoneUtil.getPlayerCardsInLibrary(p);
if (library.size() == 0)
return false;
// TODO: add some more improvements based on Destination and Type
}
else if (origin.equals("Sideboard")){
// todo: once sideboard is added
// canPlayAI for Wishes will go here
}
}
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.chkAI_Drawback();
return ((r.nextFloat() < .8) && chance);
}
private static boolean changeHiddenOriginPlayDrawbackAI(AbilityFactory af, SpellAbility sa){
// if putting cards from hand to library and parent is drawing cards
// make sure this will actually do something:
return true;
}
private static String changeHiddenOriginStackDescription(AbilityFactory af, SpellAbility sa){
// TODO: build Stack Description will need expansion as more cards are added
HashMap<String,String> params = af.getMapParams();
StringBuilder sb = new StringBuilder();
Card host = af.getHostCard();
if (!(sa instanceof Ability_Sub))
sb.append(host.getName()).append(" -");
sb.append(" ");
String origin = params.get("Origin");
String destination = params.get("Destination");
String type = params.containsKey("ChangeType") ? params.get("ChangeType") : "";
if (origin.equals("Library")){
sb.append("Search your library for ").append(params.get("ChangeNum")).append(" ").append(type).append(" and ");
sb.append("put that card ");
if (destination.equals("Battlefield")){
sb.append("onto the battlefield");
if (params.containsKey("Tapped"))
sb.append(" tapped");
sb.append(".");
}
if (destination.equals("Hand"))
sb.append("into your hand.");
if (destination.equals("Graveyard"))
sb.append("into your graveyard.");
sb.append("Then shuffle your library.");
}
else if (origin.equals("Hand")){
sb.append("Put ").append(params.get("ChangeNum")).append(" ").append(type).append(" card(s) from your hand ");
if (destination.equals("Battlefield"))
sb.append("onto the battlefield.");
if (destination.equals("Library")){
int libraryPos = params.containsKey("LibraryPosition") ? Integer.parseInt(params.get("LibraryPosition")) : 0;
if (libraryPos == 0)
sb.append("on top");
if (libraryPos == -1)
sb.append("on bottom");
sb.append(" of your library.");
}
}
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
sb.append(abSub.getStackDescription());
}
return sb.toString();
}
private static void changeHiddenOriginResolve(AbilityFactory af, SpellAbility sa){
HashMap<String,String> params = af.getMapParams();
ArrayList<Player> fetchers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
for(Player player : fetchers){
if (player.isComputer()){
changeHiddenOriginResolveAI(af, sa);
}
else{
changeHiddenOriginResolveHuman(af, sa);
}
}
}
private static void changeHiddenOriginResolveHuman(AbilityFactory af, SpellAbility sa){
HashMap<String,String> params = af.getMapParams();
Card card = af.getHostCard();
Target tgt = af.getAbTgt();
Player player;
if (tgt != null){
player = tgt.getTargetPlayers().get(0);
if (!player.canTarget(sa.getSourceCard()))
return;
}
else{
player = sa.getActivatingPlayer();
}
String origin = params.get("Origin");
String destination = params.get("Destination");
CardList fetchList = AllZoneUtil.getCardsInZone(origin, player);
if (destination.equals("Library"))
AllZone.Display.getChoice(af.getHostCard().getName() + " - Looking at " + origin, fetchList.toArray());
fetchList = filterListByType(fetchList, params, "ChangeType", sa);
PlayerZone origZone = AllZone.getZone(origin, player);
PlayerZone destZone = AllZone.getZone(destination, player);
int changeNum = params.containsKey("ChangeNum") ? Integer.parseInt(params.get("ChangeNum")) : 1;
for(int i=0; i < changeNum; i++){
if(fetchList.size() == 0 || destination == null)
break;
Object o = AllZone.Display.getChoiceOptional("Select a card", fetchList.toArray());
if(o != null) {
origZone.remove(o);
Card c = (Card) o;
fetchList.remove(c);
if (destination.equals("Library")){
// this needs to be zero indexed. Top = 0, Third = 2
int libraryPos = params.containsKey("LibraryPosition") ? Integer.parseInt(params.get("LibraryPosition")) : 0;
destZone.add(c, libraryPos);
}
else{
destZone.add(c);
if (destination.equals("Battlefield") && params.containsKey("Tapped"))
c.tap();
}
}
}
player.shuffle();
String DrawBack = params.get("SubAbility");
if (af.hasSubAbility()){
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null){
abSub.resolve();
}
else
CardFactoryUtil.doDrawBack(DrawBack, 0, card.getController(), card.getController().getOpponent(), card.getController(), card, null, sa);
}
}
private static void changeHiddenOriginResolveAI(AbilityFactory af, SpellAbility sa){
HashMap<String,String> params = af.getMapParams();
Target tgt = af.getAbTgt();
Card card = af.getHostCard();
Player player;
if (tgt != null){
player = tgt.getTargetPlayers().get(0);
if (!player.canTarget(sa.getSourceCard()))
return;
}
else{
player = sa.getActivatingPlayer();
}
String origin = params.get("Origin");
CardList fetchList = AllZoneUtil.getCardsInZone(origin, player);
fetchList = filterListByType(fetchList, params, "ChangeType", sa);
String destination = params.get("Destination");
PlayerZone origZone = AllZone.getZone(origin, player);
PlayerZone destZone = AllZone.getZone(destination, player);
String type = params.get("ChangeType");
CardList fetched = new CardList();
int changeNum = params.containsKey("ChangeNum") ? Integer.parseInt(params.get("ChangeNum")) : 1;
for(int i=0;i<changeNum;i++){
if(fetchList.size() == 0 || destination == null)
break;
// Improve the AI for fetching.
Card c;
if (type.contains("Basic"))
c = basicManaFixing(fetchList);
else if (areAllBasics(type)) // if Searching for only basics,
c = basicManaFixing(fetchList, type);
else if (fetchList.getNotType("Creature").size() == 0)
c = CardFactoryUtil.AI_getBestCreature(fetchList); //if only creatures take the best
else if (destination.equals("Battlefield"))
c = CardFactoryUtil.AI_getMostExpensivePermanent(fetchList, af.getHostCard(), false);
else if (destination.equals("Exile")){
// Exiling your own stuff, if Exiling opponents stuff choose best
if (destZone.getPlayer().isHuman())
c = CardFactoryUtil.AI_getMostExpensivePermanent(fetchList, af.getHostCard(), false);
else
c = CardFactoryUtil.AI_getCheapestPermanent(fetchList, af.getHostCard(), false);
}
else{
fetchList.shuffle();
c = fetchList.get(0);
}
fetched.add(c);
fetchList.remove(c);
}
for(Card c : fetched){
origZone.remove(c);
if (destination.equals("Library")){
int libraryPos = params.containsKey("LibraryPosition") ? Integer.parseInt(params.get("LibraryPosition")) : 0;
destZone.add(c, libraryPos);
}
else
destZone.add(c);
if (destination.equals("Battlefield") && params.containsKey("Tapped"))
c.tap();
}
AllZone.Display.getChoice(af.getHostCard().getName() + " - Computer picked:", fetched.toArray());
player.shuffle();
String DrawBack = params.get("SubAbility");
if (af.hasSubAbility()){
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null){
abSub.resolve();
}
else
CardFactoryUtil.doDrawBack(DrawBack, 0, card.getController(), card.getController().getOpponent(), card.getController(), card, null, sa);
}
}
// *********** Utility functions for Hidden ********************
private static CardList filterListByType(CardList list, HashMap<String,String> params, String type, SpellAbility sa){
if (params.containsKey(type))
list = list.getValidCards(params.get(type).split(","), sa.getActivatingPlayer(), sa.getSourceCard());
return list;
}
private static Card basicManaFixing(CardList list){ // Search for a Basic Land
return basicManaFixing(list, "Plains, Island, Swamp, Mountain, Forest");
}
private static Card basicManaFixing(CardList list, String type){ // type = basic land types
CardList combined = AllZoneUtil.getPlayerCardsInPlay(AllZone.ComputerPlayer);
combined.add(AllZoneUtil.getPlayerHand(AllZone.ComputerPlayer));
String names[] = type.split(",");
ArrayList<String> basics = new ArrayList<String>();
// what types can I go get?
for(int i = 0; i < names.length; i++){
if (list.getType(names[i]).size() != 0)
basics.add(names[i]);
}
// Which basic land is least available from hand and play, that I still have in my deck
int minSize = Integer.MAX_VALUE;
String minType = null;
for(int i = 0; i < basics.size(); i++){
String b = basics.get(i);
int num = combined.getType(names[i]).size();
if (num < minSize){
minType = b;
minSize = num;
}
}
if (minType != null)
list = list.getType(minType);
return list.get(0);
}
private static boolean areAllBasics(String types){
String[] split = types.split(",");
String names[] = {"Plains", "Island", "Swamp", "Mountain", "Forest"};
boolean[] bBasic = new boolean[split.length];
for(String s : names){
for(int i = 0; i < split.length; i++)
bBasic[i] |= s.equals(split[i]);
}
for(int i = 0; i < split.length; i++)
if (!bBasic[i])
return false;
return true;
}
// *************************************************************************************
// **************** Known Origin (Battlefield/Graveyard/Exile) *************************
// ******* Known origin cards are chosen during casting of the spell (target) **********
// *************************************************************************************
private static boolean changeKnownOriginCanPlayAI(AbilityFactory af, SpellAbility sa){
// Retrieve either this card, or target Cards in Graveyard
Ability_Cost abCost = af.getAbCost();
final Card source = af.getHostCard();
HashMap<String,String> params = af.getMapParams();
String origin = params.get("Origin");
String destination = params.get("Destination");
float pct = origin.equals("Battlefield") ? .8f : .667f;
Random r = new Random();
if (abCost != null){
// AI currently disabled for these costs
if (abCost.getSacCost()){
// Sac is ok in general, but should add some decision making based off SacType and Retrieve Type
}
if (abCost.getLifeCost()){
if (AllZone.ComputerPlayer.getLife() - abCost.getLifeAmount() < 4)
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
int currentNum = source.getCounters(abCost.getCounterType());
double percent = .25 * (currentNum / abCost.getCounterNum());
if (percent <= r.nextFloat())
return false;
}
}
if (!ComputerUtil.canPayCost(sa))
return false;
// prevent run-away activations - first time will always return true
boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getRestrictions().getNumberTurnActivations());
Target tgt = af.getAbTgt();
if(tgt != null) {
tgt.resetTargets();
CardList list = AllZoneUtil.getCardsInZone(origin);
list = list.getValidCards(tgt.getValidTgts(), AllZone.ComputerPlayer, source);
if (list.size() == 0)
return false;
// Narrow down the list:
if (origin.equals("Battlefield")){
// Bounce from Battlefield to:
// filter out untargetables
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
return CardFactoryUtil.canTarget(source, c);
}
});
}
else if (origin.equals("Graveyard")){
// Retrieve from Graveyard to:
}
if (list.size() == 0)
return false;
// target loop
while(tgt.getNumTargeted() < tgt.getMaxTargets(sa.getSourceCard(), sa)){
// AI Targeting
Card choice = null;
if (list.getNotType("Creature").size() == 0 && destination.equals("Battlefield"))
choice = CardFactoryUtil.AI_getBestCreature(list); //if only creatures take the best
else if (destination.equals("Battlefield"))
choice = CardFactoryUtil.AI_getMostExpensivePermanent(list, af.getHostCard(), false);
else{
// todo: AI needs more improvement to it's retrieval (reuse some code from spReturn here)
list.shuffle();
choice = list.get(0);
}
if (choice == null){ // can't find anything left
if (tgt.getNumTargeted() < tgt.getMinTargets(sa.getSourceCard(), sa) || tgt.getNumTargeted() == 0){
tgt.resetTargets();
return false;
}
else{
// todo is this good enough? for up to amounts?
break;
}
}
list.remove(choice);
tgt.addTarget(choice);
}
}
else{
// non-targeted retrieval
Card retrieval = null;
if (af.getMapParams().containsKey("Defined")){
// add hooks into AF_Defined function
retrieval = knownDetermineDefined(sa, params.get("Defined"), origin);
}
if (retrieval == null)
return false;
if (retrieval == source){
if (origin.equals("Graveyard")){
// return this card from graveyard: cards like Hammer of Bogardan
// in general this is cool, but we should add some type of restrictions
}
else if (origin.equals("Battlefield")){
// return this card from battlefield: cards like Blinking Spirit
// in general this should only be used to protect from Imminent Harm (dying or losing control of)
return false;
}
}
}
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.chkAI_Drawback();
return ((r.nextFloat() < pct) && chance);
}
private static boolean changeKnownOriginPlayDrawbackAI(AbilityFactory af, SpellAbility sa){
return true;
}
private static String changeKnownOriginStackDescription(AbilityFactory af, SpellAbility sa){
HashMap<String,String> params = af.getMapParams();
StringBuilder sb = new StringBuilder();
Card host = af.getHostCard();
sb.append(host.getName()).append(" - ");
if (params.containsKey("Defined"))
return sb.toString() + params.get("SpellDescription");
String destination = params.get("Destination");
String origin = params.get("Destination");
StringBuilder sbTargets = new StringBuilder();
ArrayList<Card> tgts;
if (af.getAbTgt() != null)
tgts = af.getAbTgt().getTargetCards();
else{
// otherwise add self to list and go from there
tgts = new ArrayList<Card>();
tgts.add(af.getHostCard());
}
for(Card c : tgts)
sbTargets.append(" ").append(c.getName());
String targetname = sbTargets.toString();
String pronoun = tgts.size() > 1 ? " their " : " its ";
String fromGraveyard = " from the graveyard";
// TODO: can Destination be Graveyard in any of these cases?
if (destination.equals("Battlefield")){
sb.append("Put").append(targetname);
if (origin.equals("Graveyard"))
sb.append(fromGraveyard);
sb.append(" onto the battlefield");
if (params.containsKey("Tapped"))
sb.append(" tapped");
if (params.containsKey("GainControl"))
sb.append(" under your control");
sb.append(".");
}
if(destination.equals("Hand"))
sb.append("Return").append(targetname);
if (origin.equals("Graveyard"))
sb.append(fromGraveyard);
sb.append(" to").append(pronoun).append("owners hand.");
if (destination.equals("Library")){
if (params.containsKey("Shuffle")){ // for things like Gaea's Blessing
sb.append("Shuffle").append(targetname);
sb.append(" into").append(pronoun).append("owner's library.");
}
else{
sb.append("Put").append(targetname);
if (origin.equals("Graveyard"))
sb.append(fromGraveyard);
// this needs to be zero indexed. Top = 0, Third = 2, -1 = Bottom
int libraryPosition = params.containsKey("LibraryPosition") ? Integer.parseInt(params.get("LibraryPosition")) : 0;
if (libraryPosition == -1)
sb.append(" on the bottom of").append(pronoun).append("owner's library.");
else if (libraryPosition == 0)
sb.append(" on top of").append(pronoun).append("owner's library.");
else
sb.append(libraryPosition-1).append(" from the top of").append(pronoun).append("owner's library.");
}
}
if(destination.equals("Exile")){
sb.append("Exile").append(targetname);
}
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
sb.append(abSub.getStackDescription());
if (origin.equals("Graveyard"))
sb.append(fromGraveyard);
}
return sb.toString();
}
private static void changeKnownOriginResolve(AbilityFactory af, SpellAbility sa){
ArrayList<Card> tgtCards;
HashMap<String,String> params = af.getMapParams();
Target tgt = af.getAbTgt();
Player player = sa.getActivatingPlayer();
String destination = params.get("Destination");
String origin = params.get("Origin");
if (tgt != null)
tgtCards = tgt.getTargetCards();
else{
tgtCards = new ArrayList<Card>();
Card retrieval;
if (params.containsKey("Defined"))
retrieval = knownDetermineDefined(sa, params.get("Defined"), origin);
else
retrieval = sa.getSourceCard();
tgtCards.add(retrieval);
}
for(Card tgtC : tgtCards){
PlayerZone originZone = AllZone.getZone(tgtC);
if (!originZone.is(origin))
continue;
if (tgt != null && origin.equals("Battlefield")){
// check targeting
if (!CardFactoryUtil.canTarget(sa.getSourceCard(), tgtC))
continue;
}
originZone.remove(tgtC);
Player pl = player;
if (!destination.equals("Battlefield"))
pl = tgtC.getOwner();
if (destination.equals("Library")){
// library position is zero indexed
int libraryPosition = params.containsKey("LibraryPosition") ? Integer.parseInt(params.get("LibraryPosition")) : 0;
PlayerZone library = AllZone.getZone(Constant.Zone.Library, pl);
if (libraryPosition == -1)
libraryPosition = library.size();
library.add(tgtC, libraryPosition); //move to library
if (params.containsKey("Shuffle")) // for things like Gaea's Blessing
player.shuffle();
}
else{
if (destination.equals("Battlefield")){
if (params.containsKey("Tapped"))
tgtC.tap();
if (params.containsKey("GainControl"))
tgtC.setController(sa.getActivatingPlayer());
}
AllZone.getZone(destination, pl).add(tgtC);
}
}
if (af.hasSubAbility()){
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null){
abSub.resolve();
}
else{
String DrawBack = af.getMapParams().get("SubAbility");
Card card = sa.getSourceCard();
CardFactoryUtil.doDrawBack(DrawBack, 0, card.getController(), card.getController().getOpponent(), card.getController(), card, null, sa);
}
}
}
// **************************** Known Utility **************************************
private static Card knownDetermineDefined(SpellAbility sa, String defined, String origin){
// todo: get this working in AF.getDefined stuff
CardList grave = AllZoneUtil.getCardsInZone(origin, sa.getActivatingPlayer());
if (defined.equals("Top")){
// the "top" of the graveyard, is the last to be added to the graveyard list?
if (grave.size() == 0)
return null;
return grave.get(grave.size()-1);
}
return AbilityFactory.getDefinedCards(sa.getSourceCard(), defined, sa).get(0);
}
}

View File

@@ -7417,7 +7417,7 @@ public class CardFactory implements NewConstants {
card.addSpellAbility(ability);
}//*************** END ************ END **************************
/*
//*************** START *********** START **************************
else if(cardName.equals("AEther Vial")) {
//final int[] converted = null;
@@ -7480,7 +7480,7 @@ public class CardFactory implements NewConstants {
card.addSpellAbility(ability);
}//*************** END ************ END **************************
*/
//*************** START *********** START **************************
else if(cardName.equals("Lifespark Spellbomb")) {
@@ -9351,44 +9351,6 @@ public class CardFactory implements NewConstants {
a1.setBeforePayMana(new Input_PayManaCost_Ability(a1.getManaCost(), paid1));
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Jester's Cap")) {
/*
* 2, Tap, Sacrifice Jester's Cap: Search target player's library
* for three cards and exile them. Then that player shuffles his
* or her library.
*/
final Ability_Tap ability = new Ability_Tap(card, "2") {
private static final long serialVersionUID = 222308932796127795L;
@Override
public boolean canPlayAI() {
//TODO
return false;
}
@Override
public void resolve() {
Player target = getTargetPlayer();
Player player = card.getController();
PlayerZone zone = AllZone.getZone(Constant.Zone.Library, target);
if(player.equals(AllZone.HumanPlayer)) {
AllZoneUtil.exileNCardsFromZone(zone, null, 3, true);
}
else { //computer
}
AllZone.GameAction.sacrifice(card);
}
};//Ability
card.addSpellAbility(ability);
ability.setBeforePayMana(CardFactoryUtil.input_targetPlayer(ability));
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if (cardName.equals("An-Zerrin Ruins")) {

View File

@@ -4749,66 +4749,8 @@ public class CardFactory_Creatures {
}//execute()
};
card.addDestroyCommand(destroy);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Elvish Piper")) {
final SpellAbility ability = new Ability_Tap(card, "G") {
private static final long serialVersionUID = 4414609319033894302L;
@Override
public boolean canPlayAI() {
return getCreature().size() != 0;
}
@Override
public void chooseTargetAI() {
card.tap();
Card target = CardFactoryUtil.AI_getBestCreature(getCreature());
setTargetCard(target);
}
CardList getCreature() {
CardList list = new CardList(AllZone.Computer_Hand.getCards());
list = list.getType("Creature");
return list;
}
@Override
public void resolve() {
Card c = getTargetCard();
PlayerZone hand = AllZone.getZone(Constant.Zone.Hand, card.getController());
PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, card.getController());
if(AllZone.GameAction.isCardInZone(c, hand)) {
hand.remove(c);
play.add(c);
}
}
};
ability.setBeforePayMana(new Input() {
private static final long serialVersionUID = -1647181037510967127L;
@Override
public void showMessage() {
Player controller = card.getController();
CardList creats = new CardList(AllZone.getZone(Constant.Zone.Hand, controller).getCards());
creats = creats.filter(new CardListFilter() {
public boolean addCard(Card c) {
PlayerZone zone = AllZone.getZone(c);
return c.isCreature() && zone.is(Constant.Zone.Hand);
}
});
stopSetNext(CardFactoryUtil.input_targetSpecific(ability, creats, "Select a creature", false,
false));
}
});
card.addSpellAbility(ability);
}//*************** END ************ END **************************
}
//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Jhoira of the Ghitu")) {

View File

@@ -5700,68 +5700,7 @@ public class CardFactory_Sorceries {
};//SpellAbility
card.clearSpellAbility();
card.addSpellAbility(spell);
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("Buried Alive")) {
final SpellAbility spell = new Spell(card) {
private static final long serialVersionUID = 5676345736475L;
@Override
public void resolve() {
Player player = card.getController();
if(player.equals(AllZone.HumanPlayer)) humanResolve();
else computerResolve();
}
public void humanResolve() {
for (int i=0;i<3;i++) {
PlayerZone deck = AllZone.getZone(Constant.Zone.Library, card.getController());
CardList list = new CardList(deck.getCards());
list = list.getType("Creature");
Object check = AllZone.Display.getChoiceOptional("Select a creature card", list.toArray());
if(check != null) {
PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController());
AllZone.GameAction.moveTo(grave, (Card) check);
}
AllZone.HumanPlayer.shuffle();
}
} // humanResolve
public void computerResolve() {
for (int i=0;i<3;i++) {
Card[] library = AllZone.Computer_Library.getCards();
CardList list = new CardList(library);
list = list.getType("Creature");
//pick best creature
Card c = CardFactoryUtil.AI_getBestCreature(list);
if(c == null) c = library[0];
//System.out.println("computer picked - " +c);
AllZone.Computer_Library.remove(c);
AllZone.Computer_Graveyard.add(c);
}
} // computerResolve
@Override
public boolean canPlay() {
PlayerZone library = AllZone.getZone(Constant.Zone.Library, card.getController());
return library.getCards().length != 0 && super.canPlay();
}
@Override
public boolean canPlayAI() {
CardList creature = new CardList();
creature.addAll(AllZone.Computer_Library.getCards());
creature = creature.getType("Creature");
return creature.size() > 2;
}
};//SpellAbility
card.clearSpellAbility();
card.addSpellAbility(spell);
}//*************** END ************ END **************************
}//*************** END ************ END **************************
//*************** START *********** START **************************
else if(cardName.equals("All is Dust")) {