public static Card getCard(final Card card, final String cardName, Player owner, CardFactory cf) {

        //*************** START *********** START **************************
        if (cardName.equals("Force of Savagery")) {
            SpellAbility spell = new Spell_Permanent(card) {
                private static final long serialVersionUID = 1603238129819160467L;

                @Override
                public boolean canPlayAI() {
                    CardList list = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());

                    return list.containsName("Glorious Anthem") || list.containsName("Gaea's Anthem");
                }
            };
            // Do not remove SpellAbilities created by AbilityFactory or Keywords.
            card.clearFirstSpell();
            card.addSpellAbility(spell);
        }
        //*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Gilder Bairn")) {
            Cost abCost = new Cost("2 GU Untap", cardName, true);
            Target tgt = new Target(card, "Select target permanent.", new String[]{"Permanent"});
            final Ability_Activated a1 = new Ability_Activated(card, abCost, tgt) {
                private static final long serialVersionUID = -1847685865277129366L;

                @Override
                public void resolve() {
                    Card c = getTargetCard();

                    if (c.sumAllCounters() == 0) return;
                    else if (AllZoneUtil.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c)) {
                        //zerker clean up:
                        for (Counters c_1 : Counters.values())
                            if (c.getCounters(c_1) > 0) c.addCounter(c_1, c.getCounters(c_1));
                    }
                }

                @Override
                public void chooseTargetAI() {
                    CardList perms = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
                    perms = perms.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return c.sumAllCounters() > 0 && CardFactoryUtil.canTarget(card, c);
                        }
                    });
                    perms.shuffle();
                    setTargetCard(perms.get(0)); //TODO: improve this.
                }

                @Override
                public boolean canPlayAI() {
                    CardList perms = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
                    perms = perms.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return c.sumAllCounters() > 0 && CardFactoryUtil.canTarget(card, c);
                        }
                    });
                    return perms.size() > 0;
                }
            };//SpellAbility

            card.addSpellAbility(a1);
            a1.setDescription(abCost + "For each counter on target permanent, put another of those counters on that permanent.");
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Primal Plasma") || cardName.equals("Primal Clay")) {
            card.setBaseAttack(3);
            card.setBaseDefense(3);
            final SpellAbility ability = new Ability(card, "0") {
                @Override
                public void resolve() {
                    String choice = "";
                    String choices[] = {"3/3", "2/2 with flying", "1/6 with defender"};

                    if (card.getController().isHuman()) {
                        choice = GuiUtils.getChoice("Choose one", choices);
                    } else choice = choices[MyRandom.random.nextInt(3)];

                    if (choice.equals("2/2 with flying")) {
                        card.setBaseAttack(2);
                        card.setBaseDefense(2);
                        card.addIntrinsicKeyword("Flying");
                    }
                    if (choice.equals("1/6 with defender")) {
                        card.setBaseAttack(1);
                        card.setBaseDefense(6);
                        card.addIntrinsicKeyword("Defender");
                        card.addType("Wall");
                    }

                }//resolve()
            };//SpellAbility
            Command intoPlay = new Command() {
                private static final long serialVersionUID = 8957338395786245312L;

                public void execute() {
                    StringBuilder sb = new StringBuilder();
                    sb.append(card.getName()).append(" - choose: 3/3, 2/2 flying, 1/6 defender");
                    ability.setStackDescription(sb.toString());

                    AllZone.getStack().addSimultaneousStackEntry(ability);

                }
            };
            card.addComesIntoPlayCommand(intoPlay);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Oracle of Mul Daya")) {
            final SpellAbility ability = new Ability(card, "0") {
                private static final long serialVersionUID = 2902408812353813L;

                @Override
                public void resolve() {
                    // TODO: change to static ability?
                    CardList library = AllZoneUtil.getPlayerCardsInLibrary(card.getController());
                    if (library.size() == 0)
                        return;

                    Card top = library.get(0);
                    if (top.isLand())
                        card.getController().playLand(top);
                }//resolve()

                @Override
                public boolean canPlay() {
                    CardList library = AllZoneUtil.getPlayerCardsInLibrary(card.getController());
                    if (library.size() == 0) return false;
                    PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, card.getController());
                    boolean canPlayLand = card.getController().canPlayLand();

                    return (AllZoneUtil.isCardInZone(play, card) && library.get(0).isLand() && canPlayLand);
                }
            };//SpellAbility

            StringBuilder sb = new StringBuilder();
            sb.append(card.getController()).append(" - plays land from top of library.");
            ability.setStackDescription(sb.toString());
            card.addSpellAbility(ability);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Drekavac")) {
            final Input discard = new Input() {
                private static final long serialVersionUID = -6392468000100283596L;

                @Override
                public void showMessage() {
                    AllZone.getDisplay().showMessage("Select a noncreature card to discard");
                    ButtonUtil.enableOnlyCancel();
                }

                @Override
                public void selectCard(Card c, PlayerZone zone) {
                    if (zone.is(Constant.Zone.Hand) && !c.isCreature()) {
                        c.getController().discard(c, null);
                        stop();
                    }
                }

                @Override
                public void selectButtonCancel() {
                    AllZone.getGameAction().sacrifice(card);
                    stop();
                }
            };//Input

            final SpellAbility ability = new Ability(card, "0") {
                @Override
                public void resolve() {
                    if (card.getController().isHuman()) {
                        if (AllZoneUtil.getPlayerHand(AllZone.getHumanPlayer()).size() == 0)
                            AllZone.getGameAction().sacrifice(card);
                        else AllZone.getInputControl().setInput(discard);
                    } else {
                        CardList list = AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer());
                        list = list.filter(new CardListFilter() {
                            public boolean addCard(Card c) {
                                return (!c.isCreature());
                            }
                        });
                        list.get(0).getController().discard(list.get(0), this);
                    }//else
                }//resolve()
            };//SpellAbility

            Command intoPlay = new Command() {
                private static final long serialVersionUID = 9202753910259054021L;

                public void execute() {
                    StringBuilder sb = new StringBuilder();
                    sb.append(card.getController()).append(" sacrifices Drekavac unless he discards a noncreature card");
                    ability.setStackDescription(sb.toString());

                    AllZone.getStack().addSimultaneousStackEntry(ability);

                }
            };

            SpellAbility spell = new Spell_Permanent(card) {
                private static final long serialVersionUID = -2940969025405788931L;

                //could never get the AI to work correctly
                //it always played the same card 2 or 3 times
                @Override
                public boolean canPlayAI() {
                    return false;
                }

                @Override
                public boolean canPlay() {
                    CardList list = AllZoneUtil.getPlayerHand(card.getController());
                    list.remove(card);
                    list = list.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return (!c.isCreature());
                        }
                    });
                    return list.size() != 0;
                }//canPlay()
            };
            card.addComesIntoPlayCommand(intoPlay);
            // Do not remove SpellAbilities created by AbilityFactory or Keywords.
            card.clearFirstSpell();
            card.addSpellAbility(spell);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Minotaur Explorer") || cardName.equals("Balduvian Horde") ||
                cardName.equals("Pillaging Horde")) {

            final SpellAbility creature = new Spell_Permanent(card) {
                private static final long serialVersionUID = -7326018877172328480L;

                @Override
                public boolean canPlayAI() {
                    int reqHand = 1;
                    if (AllZone.getZone(card).is(Constant.Zone.Hand))
                        reqHand++;

                    // Don't play if it would sacrifice as soon as it comes into play
                    return AllZoneUtil.getCardsInZone(Constant.Zone.Hand, AllZone.getComputerPlayer()).size() > reqHand;
                }
            };
            card.clearFirstSpell();
            card.addFirstSpellAbility(creature);

            final SpellAbility ability = new Ability(card, "0") {

                @Override
                public void resolve() {
                    CardList hand = AllZoneUtil.getPlayerHand(card.getController());
                    if (hand.size() == 0)
                        AllZone.getGameAction().sacrifice(card);
                    else
                        card.getController().discardRandom(this);
                }
            };//SpellAbility

            Command intoPlay = new Command() {
                private static final long serialVersionUID = 4986114285467649619L;

                public void execute() {
                    StringBuilder sb = new StringBuilder();
                    sb.append(card.getController()).append(" - discards at random or sacrifices ").append(cardName);
                    ability.setStackDescription(sb.toString());

                    AllZone.getStack().addSimultaneousStackEntry(ability);

                }
            };
            card.addComesIntoPlayCommand(intoPlay);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Sleeper Agent")) {
            final SpellAbility ability = new Ability(card, "0") {
                @Override
                public void resolve() {
                    // TODO: this need to be targeted
                    AllZone.getGameAction().changeController(new CardList(card), card.getController(), card.getController().getOpponent());
                }
            };

            ability.setStackDescription("When Sleeper Agent enters the battlefield, target opponent gains control of it.");
            Command intoPlay = new Command() {
                private static final long serialVersionUID = -3934471871041458847L;

                public void execute() {
                    AllZone.getStack().addSimultaneousStackEntry(ability);

                }//execute()
            };
            card.addComesIntoPlayCommand(intoPlay);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Phylactery Lich")) {
            final CommandReturn getArt = new CommandReturn() {
                //get target card, may be null
                public Object execute() {
                    CardList art = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
                    art = art.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return c.isArtifact();
                        }
                    });

                    CardList list = new CardList(art.toArray());
                    list = list.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return c.getIntrinsicKeyword().contains("Indestructible");
                        }
                    });

                    Card target = null;
                    if (!list.isEmpty())
                        target = list.get(0);
                    else if (!art.isEmpty())
                        target = art.get(0);

                    return target;
                }//execute()
            };//CommandReturn

            final SpellAbility ability = new Ability(card, "0") {
                @Override
                public void resolve() {
                    Card c = getTargetCard();

                    if (AllZoneUtil.isCardInPlay(c) && c.isArtifact()) {
                        c.addCounter(Counters.PHYLACTERY, 1);
                        card.setFinishedEnteringBF(true);
                    }
                }//resolve()
            };//SpellAbility
            Command intoPlay = new Command() {
                private static final long serialVersionUID = -1601957445498569156L;

                public void execute() {
                    Input target = new Input() {

                        private static final long serialVersionUID = -806140334868210520L;

                        @Override
                        public void showMessage() {
                            AllZone.getDisplay().showMessage("Select target artifact you control");
                            ButtonUtil.disableAll();
                        }

                        @Override
                        public void selectCard(Card card, PlayerZone zone) {
                            if (card.isArtifact() && zone.is(Constant.Zone.Battlefield) && card.getController().isHuman()) {
                                ability.setTargetCard(card);
                                AllZone.getStack().add(ability);
                                stop();
                            }
                        }
                    };//Input target


                    if (card.getController().isHuman()) {
                        CardList artifacts = AllZoneUtil.getPlayerTypeInPlay(AllZone.getHumanPlayer(), "Artifact");

                        if (artifacts.size() != 0) AllZone.getInputControl().setInput(target);

                    } else { //computer
                        Object o = getArt.execute();
                        if (o != null)//should never happen, but just in case
                        {
                            ability.setTargetCard((Card) o);
                            AllZone.getStack().addSimultaneousStackEntry(ability);

                        }
                    }//else
                }//execute()
            };
            // Do not remove SpellAbilities created by AbilityFactory or Keywords.
            card.clearFirstSpell();
            card.addSpellAbility(new Spell_Permanent(card) {

                private static final long serialVersionUID = -1506199222879057809L;

                @Override
                public boolean canPlayAI() {
                    Object o = getArt.execute();
                    return (o != null) && AllZone.getZone(getSourceCard()).is(Constant.Zone.Hand);
                }
            });
            card.addComesIntoPlayCommand(intoPlay);
        }//*************** END ************ END **************************

        
        //*************** START *********** START **************************
        else if (cardName.equals("Sky Swallower")) {
            final SpellAbility ability = new Ability(card, "0") {

                @Override
                public void resolve() {
                	//TODO - this needs to be targeted
                    Player opp = card.getController().getOpponent();

                    CardList list = AllZoneUtil.getCardsInPlay();
                    list = list.getValidCards("Card.Other+YouCtrl".split(","), card.getController(), card);

                    AllZone.getGameAction().changeController(list, card.getController(), opp);
                }//resolve()
            };//SpellAbility

            Command intoPlay = new Command() {
                private static final long serialVersionUID = -453410206437839334L;

                public void execute() {
                    StringBuilder sb = new StringBuilder();
                    sb.append(card.getController().getOpponent());
                    sb.append(" gains control of all other permanents you control");
                    ability.setStackDescription(sb.toString());

                    AllZone.getStack().addSimultaneousStackEntry(ability);

                }
            };
            card.addComesIntoPlayCommand(intoPlay);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Jhoira of the Ghitu")) {
            final Stack<Card> chosen = new Stack<Card>();
            final SpellAbility ability = new Ability(card, "2") {
                private static final long serialVersionUID = 4414609319033894302L;

                @Override
                public boolean canPlay() {
                    CardList possible = AllZoneUtil.getPlayerHand(card.getController());
                    possible = possible.filter(AllZoneUtil.nonlands);
                    return !possible.isEmpty() && super.canPlay();
                }

                public boolean canPlayAI() {
                    return false;
                }

                @Override
                public void resolve() {
                    Card c = chosen.pop();
                    c.addCounter(Counters.TIME, 4);
                    c.setSuspend(true);
                }
            };

            ability.setAfterPayMana(new Input() {
                private static final long serialVersionUID = -1647181037510967127L;

                @Override
                public void showMessage() {
                    ButtonUtil.disableAll();
                    AllZone.getDisplay().showMessage("Exile a nonland card from your hand.");
                }

                @Override
                public void selectCard(Card c, PlayerZone zone) {
                    if (zone.is(Constant.Zone.Hand) && !c.isLand()) {
                        AllZone.getGameAction().exile(c);
                        chosen.push(c);
                        ability.setStackDescription(card.toString() + " - Suspending " + c.toString());
                        AllZone.getStack().add(ability);
                        stop();
                    }
                }
            });

            card.addSpellAbility(ability);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Hermit Druid")) {
            Cost abCost = new Cost("G T", cardName, true);
            final Ability_Activated ability = new Ability_Activated(card, abCost, null) {
                private static final long serialVersionUID = 5884624727757154056L;

                @Override
                public boolean canPlayAI() {
                    //Use the ability if there is still a forest in the library
                    CardList library = AllZoneUtil.getPlayerCardsInLibrary(card.getController());
                    return !library.getName("Forest").isEmpty();
                }

                @Override
                public void resolve() {
                    CardList library = AllZoneUtil.getPlayerCardsInLibrary(card.getController());
                    if (library.size() == 0) return;    // maybe provide some notification that library is empty?

                    CardList revealed = new CardList();

                    Card basicGrab = null;

                    int count = 0;
                    // reveal top card until library runs out or hit a basic land
                    while (basicGrab == null) {
                        Card top = library.get(count);
                        count++;
                        revealed.add(top);

                        if (top.isBasicLand())
                            basicGrab = top;

                        if (count == library.size())
                            break;
                    }//while
                    GuiUtils.getChoiceOptional("Revealed cards:", revealed.toArray());

                    if (basicGrab != null) {
                        // put basic in hand
                        AllZone.getGameAction().moveToHand(basicGrab);
                        revealed.remove(basicGrab);
                    }
                    // place revealed cards in graveyard (TODO: player should choose order)
                    for (Card c : revealed) {
                        AllZone.getGameAction().moveToGraveyard(c);
                    }
                }
            };
            ability.setStackDescription(abCost + "Reveal cards from the top of your library until you reveal a basic land card." +
                    " Put that card into your hand and all other cards revealed this way into your graveyard.");
            card.addSpellAbility(ability);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Vedalken Plotter")) {
            final Card[] target = new Card[2];
            final int[] index = new int[1];

            final Ability ability = new Ability(card, "") {

                private static final long serialVersionUID = -3075569295823682336L;

                @Override
                public boolean canPlayAI() {
                    return false;
                }

                @Override
                public void resolve() {
                    Card crd0 = target[0];
                    Card crd1 = target[1];

                    if (crd0 != null && crd1 != null) {
                        Player p0 = crd0.getController();
                        Player p1 = crd1.getController();
                        AllZone.getGameAction().changeController(new CardList(crd0), p0, p1);
                        AllZone.getGameAction().changeController(new CardList(crd1), p1, p0);
                    }

                }//resolve()
            };//SpellAbility


            final Input input = new Input() {

                private static final long serialVersionUID = -7143706716256752987L;

                @Override
                public void showMessage() {
                    if (index[0] == 0) AllZone.getDisplay().showMessage("Select target land you control.");
                    else AllZone.getDisplay().showMessage("Select target land opponent controls.");

                    ButtonUtil.enableOnlyCancel();
                }

                @Override
                public void selectButtonCancel() {
                    stop();
                }

                @Override
                public void selectCard(Card c, PlayerZone zone) {
                    //must target creature you control
                    if (index[0] == 0 && !c.getController().equals(card.getController())) return;

                    //must target creature you don't control
                    if (index[0] == 1 && c.getController().equals(card.getController())) return;


                    if (c.isLand() && zone.is(Constant.Zone.Battlefield) && CardFactoryUtil.canTarget(card, c)) {
                        //System.out.println("c is: " +c);
                        target[index[0]] = c;
                        index[0]++;
                        showMessage();

                        if (index[0] == target.length) {
                            AllZone.getStack().add(ability);
                            stop();
                        }
                    }
                }//selectCard()
            };//Input

            Command comesIntoPlay = new Command() {
                private static final long serialVersionUID = 6513203926272187582L;

                public void execute() {
                    index[0] = 0;
                    if (card.getController().isHuman()) AllZone.getInputControl().setInput(input);
                }
            };

            StringBuilder sb = new StringBuilder();
            sb.append(cardName).append(" - Exchange control of target land you control and target land an opponent controls.");
            ability.setStackDescription(sb.toString());

            card.addComesIntoPlayCommand(comesIntoPlay);
        }//*************** END ************ END **************************

        
        //*************** START *********** START **************************
        else if (cardName.equals("Wojek Embermage")) {
            Cost abCost = new Cost("T", cardName, true);
            Target tgt = new Target(card, "TgtC");
            final Ability_Activated ability = new Ability_Activated(card, abCost, tgt) {
                private static final long serialVersionUID = -1208482961653326721L;

                @Override
                public boolean canPlayAI() {
                    return (CardFactoryUtil.AI_getHumanCreature(1, card, true).size() != 0)
                            && (AllZone.getPhase().getPhase().equals(Constant.Phase.Main2));
                }

                @Override
                public void chooseTargetAI() {
                    CardList list = CardFactoryUtil.AI_getHumanCreature(1, card, true);
                    list.shuffle();
                    setTargetCard(list.get(0));
                }

                @Override
                public void resolve() {
                    if (AllZoneUtil.isCardInPlay(getTargetCard())
                            && CardFactoryUtil.canTarget(card, getTargetCard())) {
                        CardList list = getRadiance(getTargetCard());
                        for (int i = 0; i < list.size(); i++) {
                            list.get(i).addDamage(1, card);
                        }
                    }
                }//resolve()

                //parameter Card c, is included in CardList
                //no multi-colored cards
                CardList getRadiance(Card c) {
                    if (CardUtil.getColors(c).contains(Constant.Color.Colorless)) {
                        CardList list = new CardList();
                        list.add(c);
                        return list;
                    }

                    CardList sameColor = new CardList();
                    CardList list = AllZoneUtil.getCreaturesInPlay();

                    for (int i = 0; i < list.size(); i++)
                        if (list.get(i).sharesColorWith(c)) sameColor.add(list.get(i));

                    return sameColor;
                }

            };//SpellAbility
            card.addSpellAbility(ability);
            ability.setDescription("Radiance - " + abCost + cardName + " deals 1 damage to target creature and each other creature that shares a color with it.");

        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Adarkar Valkyrie")) {
            //tap ability - no cost - target creature - EOT

            final Card[] target = new Card[1];

            final Command destroy = new Command() {
            	private static final long serialVersionUID = -2433442359225521472L;

            	public void execute() {

            		AllZone.getStack().addSimultaneousStackEntry(new Ability(card, "0", "Adarkar Valkyrie - Return " + target[0] + " from graveyard to the battlefield") {
            			@Override
            			public void resolve() {
            				PlayerZone grave = AllZone.getZone(target[0]);
            				//checks to see if card is still in the graveyard

            				if (grave != null && AllZoneUtil.isCardInZone(grave, target[0])) {
            					PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, card.getController());
            					target[0].setController(card.getController());
            					AllZone.getGameAction().moveTo(play, target[0]);
            				}
            			}
            		});
            	}//execute()
            };

            final Command untilEOT = new Command() {
                private static final long serialVersionUID = 2777978927867867610L;

                public void execute() {
                    //resets the Card destroy Command
                    target[0].removeDestroyCommand(destroy);
                }
            };

            Cost abCost = new Cost("T", cardName, true);
            Target tgt = new Target(card, "Target creature other than " + cardName, "Creature.Other".split(","));
            final Ability_Activated ability = new Ability_Activated(card, abCost, tgt) {
                private static final long serialVersionUID = -8454685126878522607L;

                @Override
                public void resolve() {
                    if (AllZoneUtil.isCardInPlay(getTargetCard())) {
                        target[0] = getTargetCard();

                        if (!target[0].isToken()) {    // not necessary, but will help speed up stack resolution
                            AllZone.getEndOfTurn().addUntil(untilEOT);
                            target[0].addDestroyCommand(destroy);
                        }
                    }//if
                }//resolve()

                @Override
                public boolean canPlayAI() {
                    return false;
                }
            };//SpellAbility

            card.addSpellAbility(ability);

            StringBuilder sb = new StringBuilder();
            sb.append("tap: When target creature other than Adarkar Valkyrie is put into a ");
            sb.append("graveyard this turn, return that card to the battlefield under your control.");
            ability.setDescription(sb.toString());
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Painter's Servant")) {
            final long[] timeStamp = new long[1];
            final String[] color = new String[1];

            Command comesIntoPlay = new Command() {
                private static final long serialVersionUID = 333134223161L;

                public void execute() {
                    if (card.getController().isHuman()) {
                        String[] colors = Constant.Color.onlyColors;

                        Object o = GuiUtils.getChoice("Choose color", colors);
                        color[0] = (String) o;
                        card.setChosenColor(color[0]);
                    } else {
                        // AI chooses the color that appears in the keywords of the most cards in its deck, hand and on battlefield
                        CardList list = new CardList();
                        list.addAll(AllZoneUtil.getPlayerCardsInLibrary(AllZone.getComputerPlayer()));
                        list.addAll(AllZoneUtil.getPlayerHand(AllZone.getComputerPlayer()));
                        list.addAll(AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer()));

                        color[0] = Constant.Color.White;
                        int max = list.getKeywordsContain(color[0]).size();

                        String[] colors = {Constant.Color.Blue, Constant.Color.Black, Constant.Color.Red, Constant.Color.Green};
                        for (String c : colors) {
                            int cmp = list.getKeywordsContain(c).size();
                            if (cmp > max) {
                                max = cmp;
                                color[0] = c;
                            }
                        }
                        card.setChosenColor(color[0]);
                    }

                    String s = CardUtil.getShortColor(color[0]);
                    timeStamp[0] = AllZone.getGameInfo().addColorChanges(s, card, true, true);
                }
            };//Command

            Command leavesBattlefield = new Command() {
                private static final long serialVersionUID = 2559212590399132459L;

                public void execute() {
                    String s = CardUtil.getShortColor(color[0]);
                    AllZone.getGameInfo().removeColorChanges(s, card, true, timeStamp[0]);
                }
            };

            card.addComesIntoPlayCommand(comesIntoPlay);
            card.addLeavesPlayCommand(leavesBattlefield);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Stangg")) {

            final Ability ability = new Ability(card, "0") {
                @Override
                public void resolve() {
                    CardList cl = CardFactoryUtil.makeToken("Stangg Twin", "RG 3 4 Stangg Twin", card.getController(), "R G",
                            new String[]{"Legendary", "Creature", "Human", "Warrior"}, 3, 4, new String[]{""});

                    cl.get(0).addLeavesPlayCommand(new Command() {
                        private static final long serialVersionUID = 3367390368512271319L;

                        public void execute() {
                            if (AllZoneUtil.isCardInPlay(card)) AllZone.getGameAction().sacrifice(card);
                        }
                    });
                }
            };
            ability.setStackDescription("When Stangg enters the battlefield, if Stangg is on the battlefield, put a legendary 3/4 red and green Human Warrior creature token named Stangg Twin onto the battlefield.");

            card.addComesIntoPlayCommand(new Command() {
                private static final long serialVersionUID = 6667896040611028600L;

                public void execute() {
                    AllZone.getStack().addSimultaneousStackEntry(ability);

                }
            });

            card.addLeavesPlayCommand(new Command() {
                private static final long serialVersionUID = 1786900359843939456L;

                public void execute() {
                    CardList list = AllZoneUtil.getCardsInPlay("Stangg Twin");

                    if (list.size() == 1) AllZone.getGameAction().exile(list.get(0));
                }
            });
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Horde of Notions")) {
            final Ability ability = new Ability(card, "W U B R G") {
                @Override
                public void resolve() {
                    Card c = null;
                    if (card.getController().isHuman()) {
                        Object o = GuiUtils.getChoiceOptional("Select Elemental", getCreatures());
                        c = (Card) o;

                    } else {
                        c = getAIElemental();
                    }

                    if (AllZoneUtil.isCardInPlayerGraveyard(card.getController(), c)) {
                        PlayerZone play = AllZone.getZone(Constant.Zone.Battlefield, c.getController());
                        AllZone.getGameAction().moveTo(play, c);
                    }
                }//resolve()

                @Override
                public boolean canPlay() {
                    return getCreatures().size() != 0 && AllZoneUtil.isCardInPlay(card) && super.canPlay();
                }

                public CardList getCreatures() {
                    CardList creatures = AllZoneUtil.getPlayerTypeInGraveyard(card.getController(), "Elemental");
                    return creatures;
                }

                public Card getAIElemental() {
                    CardList c = getCreatures();
                    Card biggest = c.get(0);
                    for (int i = 0; i < c.size(); i++)
                        if (biggest.getNetAttack() < c.get(i).getNetAttack()) biggest = c.get(i);

                    return biggest;
                }
            };//SpellAbility
            card.addSpellAbility(ability);

            ability.setDescription("W U B R G: You may play target Elemental card from your graveyard without paying its mana cost.");
            ability.setStackDescription("Horde of Notions - play Elemental card from graveyard without paying its mana cost.");
            ability.setBeforePayMana(new Input_PayManaCost(ability));
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Rhys the Redeemed")) {

            Cost abCost = new Cost("4 GW GW T", card.getName(), true);
            final Ability_Activated copyTokens1 = new Ability_Activated(card, abCost, null) {
                private static final long serialVersionUID = 6297992502069547478L;

                @Override
                public void resolve() {
                    CardList allTokens = AllZoneUtil.getCreaturesInPlay(card.getController());
                    allTokens = allTokens.filter(AllZoneUtil.token);

                    int multiplier = AllZoneUtil.getDoublingSeasonMagnitude(card.getController());

                    for (int i = 0; i < allTokens.size(); i++) {
                        Card c = allTokens.get(i);
                        for (int j = 0; j < multiplier; j++)
                            copyToken(c);
                    }
                }

                public void copyToken(Card token) {
                    Card copy = new Card();
                    copy.setName(token.getName());
                    copy.setImageName(token.getImageName());

                    copy.setOwner(token.getController());
                    copy.setController(token.getController());
                    copy.setManaCost(token.getManaCost());
                    copy.setColor(token.getColor());
                    copy.setToken(true);
                    copy.setType(token.getType());
                    copy.setBaseAttack(token.getBaseAttack());
                    copy.setBaseDefense(token.getBaseDefense());

                    AllZone.getGameAction().moveToPlay(copy);
                }

                @Override
                public boolean canPlayAI() {
                    CardList allTokens = AllZoneUtil.getCreaturesInPlay(AllZone.getComputerPlayer());
                    allTokens = allTokens.filter(AllZoneUtil.token);

                    return allTokens.size() >= 2;
                }
            };

            card.addSpellAbility(copyTokens1);
            copyTokens1.setDescription(abCost + "For each creature token you control, put a token that's a copy of that creature onto the battlefield.");
            StringBuilder sb = new StringBuilder();
            sb.append(card.getName()).append(" - For each creature token you control, put a token that's a copy of that creature onto the battlefield.");
            copyTokens1.setStackDescription(sb.toString());
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Treva, the Renewer")) {
            final Player player = card.getController();

            final Ability ability2 = new Ability(card, "2 W") {
                @Override
                public void resolve() {
                    int lifeGain = 0;
                    if (card.getController().isHuman()) {
                        String choices[] = {"white", "blue", "black", "red", "green"};
                        Object o = GuiUtils.getChoiceOptional("Select Color: ", choices);
                        Log.debug("Treva, the Renewer", "Color:" + o);
                        lifeGain = CardFactoryUtil.getNumberOfPermanentsByColor((String) o);

                    } else {
                        CardList list = AllZoneUtil.getCardsInPlay();
                        String color = CardFactoryUtil.getMostProminentColor(list);
                        lifeGain = CardFactoryUtil.getNumberOfPermanentsByColor(color);
                    }

                    card.getController().gainLife(lifeGain, card);
                }

                @Override
                public boolean canPlay() {
                    //this is set to false, since it should only TRIGGER
                    return false;
                }
            };// ability2
            //card.clearSpellAbility();
            card.addSpellAbility(ability2);

            StringBuilder sb2 = new StringBuilder();
            sb2.append(card.getName()).append(" - ").append(player);
            sb2.append(" gains life equal to permanents of the chosen color.");
            ability2.setStackDescription(sb2.toString());
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Rith, the Awakener")) {
            final Player player = card.getController();

            final Ability ability2 = new Ability(card, "2 G") {
                @Override
                public void resolve() {
                    int numberTokens = 0;
                    if (card.getController().isHuman()) {
                        String choices[] = {"white", "blue", "black", "red", "green"};
                        Object o = GuiUtils.getChoiceOptional("Select Color: ", choices);
                        //System.out.println("Color:" + o);
                        numberTokens = CardFactoryUtil.getNumberOfPermanentsByColor((String) o);
                    } else {
                        CardList list = AllZoneUtil.getCardsInPlay();
                        String color = CardFactoryUtil.getMostProminentColor(list);
                        numberTokens = CardFactoryUtil.getNumberOfPermanentsByColor(color);
                    }

                    for (int i = 0; i < numberTokens; i++) {
                        CardFactoryUtil.makeTokenSaproling(card.getController());
                    }
                }

                @Override
                public boolean canPlay() {
                    //this is set to false, since it should only TRIGGER
                    return false;
                }
            };// ability2
            //card.clearSpellAbility();
            card.addSpellAbility(ability2);

            StringBuilder sb2 = new StringBuilder();
            sb2.append(card.getName()).append(" - ").append(player);
            sb2.append(" puts a 1/1 green Saproling creature token onto the battlefield for each permanent of the chosen color");
            ability2.setStackDescription(sb2.toString());
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Sphinx of Jwar Isle")) {
            final SpellAbility ability1 = new Ability(card, "0") {
                @Override
                public void resolve() {
                    Player player = card.getController();
                    PlayerZone lib = AllZone.getZone(Constant.Zone.Library, player);

                    if (lib.size() < 1) return;

                    CardList cl = new CardList();
                    cl.add(lib.get(0));

                    GuiUtils.getChoiceOptional("Top card", cl.toArray());
                }

                @Override
                public boolean canPlayAI() {
                    return false;
                }
            };//SpellAbility

            StringBuilder sb1 = new StringBuilder();
            sb1.append(card.getName()).append(" - look at top card of library.");
            ability1.setStackDescription(sb1.toString());

            ability1.setDescription("You may look at the top card of your library.");
            card.addSpellAbility(ability1);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Master of the Wild Hunt")) {

            final Cost abCost = new Cost("T", cardName, true);
            final Target abTgt = new Target(card, "Target a creature to Hunt", "Creature".split(","));
            final Ability_Activated ability = new Ability_Activated(card, abCost, abTgt) {
                private static final long serialVersionUID = 35050145102566898L;

                @Override
                public boolean canPlayAI() {
                    CardList wolves = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
                    wolves = wolves.getType("Wolf");

                    wolves = wolves.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return c.isUntapped() && c.isCreature();
                        }
                    });
                    int power = 0;
                    for (int i = 0; i < wolves.size(); i++)
                        power += wolves.get(i).getNetAttack();

                    if (power == 0)
                        return false;

                    final int totalPower = power;

                    CardList targetables = AllZoneUtil.getPlayerCardsInPlay(AllZone.getHumanPlayer());

                    targetables = targetables.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return CardFactoryUtil.canTarget(card, c) && c.isCreature() && c.getNetDefense() <= totalPower;
                        }
                    });

                    if (targetables.size() == 0)
                        return false;

                    getTarget().resetTargets();
                    setTargetCard(CardFactoryUtil.AI_getBestCreature(targetables));

                    return true;
                }

                @Override
                public void resolve() {
                    CardList wolves = AllZoneUtil.getPlayerCardsInPlay(card.getController());
                    wolves = wolves.getType("Wolf");

                    wolves = wolves.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return c.isUntapped() && c.isCreature();
                        }
                    });

                    final Card target = getTargetCard();

                    if (wolves.size() == 0)
                        return;

                    if (!(CardFactoryUtil.canTarget(card, target) && AllZoneUtil.isCardInPlay(target)))
                        return;

                    for (Card c : wolves) {
                        c.tap();
                        target.addDamage(c.getNetAttack(), c);
                    }

                    if (target.getController().isHuman()) {    // Human choose spread damage
                        for (int x = 0; x < target.getNetAttack(); x++) {
                            AllZone.getInputControl().setInput(CardFactoryUtil.MasteroftheWildHunt_input_targetCreature(this, wolves, new Command() {
                                private static final long serialVersionUID = -328305150127775L;

                                public void execute() {
                                    getTargetCard().addDamage(1, target);
                                    AllZone.getGameAction().checkStateEffects();
                                }
                            }));
                        }
                    } else {        // AI Choose spread Damage
                        CardList damageableWolves = wolves.filter(new CardListFilter() {
                            public boolean addCard(Card c) {
                                return (c.predictDamage(target.getNetAttack(), target, false) > 0);
                            }
                        });

                        if (damageableWolves.size() == 0)    // don't bother if I can't damage anything
                            return;

                        CardList wolvesLeft = damageableWolves.filter(new CardListFilter() {
                            public boolean addCard(Card c) {
                                return !c.hasKeyword("Indestructible");
                            }
                        });

                        for (int i = 0; i < target.getNetAttack(); i++) {
                            wolvesLeft = wolvesLeft.filter(new CardListFilter() {
                                public boolean addCard(Card c) {
                                    return c.getKillDamage() > 0 && (c.getKillDamage() <= target.getNetAttack()
                                            || target.hasKeyword("Deathtouch"));
                                }
                            });

                            // Kill Wolves that can be killed first
                            if (wolvesLeft.size() > 0) {
                                Card best = CardFactoryUtil.AI_getBestCreature(wolvesLeft);
                                best.addDamage(1, target);
                                if (best.getKillDamage() <= 0 || target.hasKeyword("Deathtouch")) {
                                    wolvesLeft.remove(best);
                                }
                            } else {
                                // Add -1/-1s to Random Indestructibles
                                if (target.hasKeyword("Infect") || target.hasKeyword("Wither")) {
                                    CardList indestructibles = damageableWolves.filter(new CardListFilter() {
                                        public boolean addCard(Card c) {
                                            return c.hasKeyword("Indestructible");
                                        }
                                    });
                                    indestructibles.shuffle();
                                    indestructibles.get(0).addDamage(1, target);
                                }

                                // Then just add Damage randomnly

                                else {
                                    damageableWolves.shuffle();
                                    wolves.get(0).addDamage(1, target);
                                }
                            }
                        }
                    }
                }//resolve()
            };//SpellAbility

            StringBuilder sb = new StringBuilder();
            sb.append("Tap: Tap all untapped Wolf creatures you control. Each Wolf tapped ");
            sb.append("this way deals damage equal to its power to target creature. That creature deals ");
            sb.append("damage equal to its power divided as its controller chooses among any number of those Wolves.");
            ability.setDescription(sb.toString());

            card.addSpellAbility(ability);
        }//*************** END ************ END **************************

/*
        //*************** START *********** START **************************
        else if (cardName.equals("Figure of Destiny")) {
            Ability ability1 = new Ability(card, "RW") {
                @Override
                public void resolve() {
                    boolean artifact = false;
                    card.setBaseAttack(2);
                    card.setBaseDefense(2);

                    card.removeIntrinsicKeyword("Flying");
                    card.removeIntrinsicKeyword("First Strike");

                    if (card.isArtifact()) artifact = true;

                    card.setType(new ArrayList<String>());
                    if (artifact) card.addType("Artifact");
                    card.addType("Creature");
                    card.addType("Kithkin");
                    card.addType("Spirit");
                }

                @Override
                public boolean canPlayAI() {
                    return !card.isType("Spirit")
                            && super.canPlayAI();
                }

            };// ability1

            ability1.setDescription("RW: Figure of Destiny becomes a 2/2 Kithkin Spirit.");
            ability1.setStackDescription("Figure of Destiny becomes a 2/2 Kithkin Spirit.");
            card.addSpellAbility(ability1);


            Ability ability2 = new Ability(card, "RW RW RW") {
                @Override
                public void resolve() {
                    if (card.isType("Spirit")) {
                        boolean artifact = false;
                        card.setBaseAttack(4);
                        card.setBaseDefense(4);

                        card.removeIntrinsicKeyword("Flying");
                        card.removeIntrinsicKeyword("First Strike");

                        if (card.isArtifact()) artifact = true;

                        card.setType(new ArrayList<String>());
                        if (artifact) card.addType("Artifact");
                        card.addType("Creature");
                        card.addType("Kithkin");
                        card.addType("Spirit");
                        card.addType("Warrior");
                    }
                }

                @Override
                public boolean canPlay() {
                    return card.isType("Spirit")
                            && super.canPlay();
                }

                @Override
                public boolean canPlayAI() {
                    return !card.isType("Warrior")
                            && super.canPlayAI();
                }

            };// ability2

            ability2.setDescription("RW RW RW: If Figure of Destiny is a Spirit, it becomes a 4/4 Kithkin Spirit Warrior.");
            ability2.setStackDescription("Figure of Destiny becomes a 4/4 Kithkin Spirit Warrior.");
            card.addSpellAbility(ability2);


            Ability ability3 = new Ability(card, "RW RW RW RW RW RW") {
                @Override
                public void resolve() {
                    if (card.isType("Warrior")) {
                        boolean artifact = false;
                        card.setBaseAttack(8);
                        card.setBaseDefense(8);

                        card.addIntrinsicKeyword("Flying");
                        card.addIntrinsicKeyword("First Strike");

                        if (card.isArtifact()) artifact = true;

                        card.setType(new ArrayList<String>());
                        if (artifact) card.addType("Artifact");
                        card.addType("Creature");
                        card.addType("Kithkin");
                        card.addType("Spirit");
                        card.addType("Warrior");
                        card.addType("Avatar");
                    }
                }

                @Override
                public boolean canPlay() {
                    return card.isType("Warrior")
                            && super.canPlay();
                }

                @Override
                public boolean canPlayAI() {
                    return !card.isType("Avatar")
                            && super.canPlayAI();
                }
            };// ability3

            StringBuilder sbDesc = new StringBuilder();
            sbDesc.append("RW RW RW RW RW RW: If Figure of Destiny is a Warrior, it becomes ");
            sbDesc.append("an 8/8 Kithkin Spirit Warrior Avatar with flying and first strike.");
            ability3.setDescription(sbDesc.toString());

            ability3.setStackDescription("Figure of Destiny becomes an 8/8 Kithkin Spirit Warrior Avatar with flying and first strike.");
            card.addSpellAbility(ability3);
        }//*************** END ************ END **************************

*/
        //*************** START *********** START **************************
        else if (cardName.equals("Cantivore")) {
            SpellAbility spell = new Spell_Permanent(card) {
                private static final long serialVersionUID = 7254358703158629514L;

                @Override
                public boolean canPlayAI() {
                    CardList list = AllZoneUtil.getPlayerGraveyard(AllZone.getComputerPlayer());
                    list.addAll(AllZoneUtil.getPlayerGraveyard(AllZone.getHumanPlayer()));
                    list = list.getType("Enchantment");
                    return super.canPlayAI() && list.size() > 0;
                }
            };
            // Do not remove SpellAbilities created by AbilityFactory or Keywords.
            card.clearFirstSpell();
            card.addSpellAbility(spell);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Terravore")) {
            SpellAbility spell = new Spell_Permanent(card) {
                private static final long serialVersionUID = 7316190829288665283L;

                @Override
                public boolean canPlayAI() {
                    CardList list = AllZoneUtil.getPlayerGraveyard(AllZone.getComputerPlayer());
                    list.addAll(AllZoneUtil.getPlayerGraveyard(AllZone.getHumanPlayer()));
                    list = list.getType("Land");
                    return super.canPlayAI() && list.size() > 0;
                }
            };
            // Do not remove SpellAbilities created by AbilityFactory or Keywords.
            card.clearFirstSpell();
            card.addSpellAbility(spell);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Mortivore")) {
            SpellAbility spell = new Spell_Permanent(card) {
                private static final long serialVersionUID = -7118801410173525870L;

                @Override
                public boolean canPlayAI() {
                    CardList list = AllZoneUtil.getPlayerGraveyard(AllZone.getComputerPlayer());
                    list.addAll(AllZoneUtil.getPlayerGraveyard(AllZone.getHumanPlayer()));
                    list = list.getType("Creature");
                    return super.canPlayAI() && list.size() > 0;
                }
            };
            // Do not remove SpellAbilities created by AbilityFactory or Keywords.
            card.clearFirstSpell();
            card.addSpellAbility(spell);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Cognivore")) {
            SpellAbility spell = new Spell_Permanent(card) {
                private static final long serialVersionUID = -2216181341715046786L;

                @Override
                public boolean canPlayAI() {
                    CardList list = AllZoneUtil.getPlayerGraveyard(AllZone.getComputerPlayer());
                    list.addAll(AllZoneUtil.getPlayerGraveyard(AllZone.getHumanPlayer()));
                    list = list.getType("Instant");
                    return super.canPlayAI() && list.size() > 0;
                }
            };
            // Do not remove SpellAbilities created by AbilityFactory or Keywords.
            card.clearFirstSpell();
            card.addSpellAbility(spell);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Magnivore")) {
            SpellAbility spell = new Spell_Permanent(card) {
                private static final long serialVersionUID = -2252263708643462897L;

                @Override
                public boolean canPlayAI() {
                    CardList list = AllZoneUtil.getPlayerGraveyard(AllZone.getComputerPlayer());
                    list.addAll(AllZoneUtil.getPlayerGraveyard(AllZone.getHumanPlayer()));
                    list = list.getType("Sorcery");
                    return super.canPlayAI() && list.size() > 0;
                }
            };
            // Do not remove SpellAbilities created by AbilityFactory or Keywords.
            card.clearFirstSpell();
            card.addSpellAbility(spell);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Shifting Wall") || cardName.equals("Maga, Traitor to Mortals") || cardName.equals("Feral Hydra")
                || cardName.equals("Krakilin") || cardName.equals("Ivy Elemental") || cardName.equals("Lightning Serpent")) {

            SpellAbility spell = new Spell_Permanent(card) {
                private static final long serialVersionUID = 7708945715867177172L;

                @Override
                public boolean canPlayAI() {
                    return super.canPlay() && 4 <= ComputerUtil.getAvailableMana().size() - CardUtil.getConvertedManaCost(card.getManaCost());
                }
            };
            card.clearFirstSpell();
            card.addFirstSpellAbility(spell);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Apocalypse Hydra")) {
            SpellAbility spell = new Spell_Permanent(card) {
                private static final long serialVersionUID = -11489323313L;

                @Override
                public boolean canPlayAI() {
                    return super.canPlay() && 5 <= ComputerUtil.getAvailableMana().size() - 2;
                }

                @Override
                public void resolve() {
                    int XCounters = card.getXManaCostPaid();
                    Card c = AllZone.getGameAction().moveToPlay(getSourceCard());

                    if (XCounters >= 5) XCounters = 2 * XCounters;
                    c.addCounter(Counters.P1P1, XCounters);
                }
            };
            // Do not remove SpellAbilities created by AbilityFactory or Keywords.
            card.clearFirstSpell();
            card.addSpellAbility(spell);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Molten Hydra")) {
            Target target = new Target(card, "TgtCP");
            Cost abCost = new Cost("T", cardName, true);
            final Ability_Activated ability2 = new Ability_Activated(card, abCost, target) {
                private static final long serialVersionUID = 2626619319289064289L;

                @Override
                public boolean canPlay() {
                    return card.getCounters(Counters.P1P1) > 0 && super.canPlay();
                }

                @Override
                public boolean canPlayAI() {
                    return getCreature().size() != 0;
                }

                @Override
                public void chooseTargetAI() {
                    if (AllZone.getHumanPlayer().getLife() < card.getCounters(Counters.P1P1))
                        setTargetPlayer(AllZone.getHumanPlayer());
                    else {
                        CardList list = getCreature();
                        list.shuffle();
                        setTargetCard(list.get(0));
                    }
                }//chooseTargetAI()

                CardList getCreature() {

                    //toughness of 1
                    CardList list = CardFactoryUtil.AI_getHumanCreature(card.getCounters(Counters.P1P1), card, true);
                    list = list.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            int total = card.getCounters(Counters.P1P1);
                            return (total >= c.getKillDamage());
                        }
                    });
                    return list;
                }//getCreature()

                @Override
                public void resolve() {
                    int total = card.getCounters(Counters.P1P1);
                    if (getTargetCard() != null) {
                        if (AllZoneUtil.isCardInPlay(getTargetCard())
                                && CardFactoryUtil.canTarget(card, getTargetCard())) getTargetCard().addDamage(total,
                                card);
                    } else getTargetPlayer().addDamage(total, card);
                    card.subtractCounter(Counters.P1P1, total);
                }//resolve()
            };//SpellAbility

            card.addSpellAbility(ability2);

            StringBuilder sb = new StringBuilder();
            sb.append(abCost + "Remove all +1/+1 counters from " + cardName + ":  " + cardName);
            sb.append(" deals damage to target creature or player equal to the number of +1/+1 counters removed this way.");
            ability2.setDescription(sb.toString());

            ability2.setStackDescription("Molten Hydra deals damage to number of +1/+1 counters on it to target creature or player.");
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Academy Rector") || cardName.equals("Lost Auramancers")) {
            final SpellAbility ability = new Ability(card, "0") {

                @Override
                public void resolve() {

                    if (card.getController().isHuman()) {
                        StringBuilder question = new StringBuilder();
                        if (card.getName().equals("Academy Rector")) {
                            question.append("Exile ").append(card.getName()).append(" and place ");
                        } else {
                            question.append("Place ");
                        }
                        question.append("an enchantment from your library onto the battlefield?");

                        if (GameActionUtil.showYesNoDialog(card, question.toString())) {
                            if (card.getName().equals("Academy Rector")) {
                                AllZone.getGameAction().exile(card);
                            }
                            CardList list = AllZoneUtil.getPlayerCardsInLibrary(AllZone.getHumanPlayer());
                            list = list.getType("Enchantment");

                            if (list.size() > 0) {
                                Object objectSelected = GuiUtils.getChoiceOptional("Choose an enchantment", list.toArray());

                                if (objectSelected != null) {

                                    final Card c = (Card) objectSelected;
                                    AllZone.getGameAction().moveToPlay(c);

                                    if (c.isAura()) {

                                        String enchantThisType[] = {""};
                                        String message[] = {""};

                                        // The type following "Enchant" maybe upercase or lowercase, cardsfolder has both
                                        // Note that I am being overly cautious.

                                        if (c.hasKeyword("Enchant creature without flying")
                                                || c.hasKeyword("Enchant Creature without flying")) {
                                            enchantThisType[0] = "Creature.withoutFlying";
                                            message[0] = "Select a creature without flying";
                                        } else if (c.hasKeyword("Enchant creature with converted mana cost 2 or less")
                                                || c.hasKeyword("Enchant Creature with converted mana cost 2 or less")) {
                                            enchantThisType[0] = "Creature.cmcLE2";
                                            message[0] = "Select a creature with converted mana cost 2 or less";
                                        } else if (c.hasKeyword("Enchant red or green creature")) {
                                            enchantThisType[0] = "Creature.Red,Creature.Green";
                                            message[0] = "Select a red or green creature";
                                        } else if (c.hasKeyword("Enchant tapped creature")) {
                                            enchantThisType[0] = "Creature.tapped";
                                            message[0] = "Select a tapped creature";
                                        } else if (c.hasKeyword("Enchant creature")
                                                || c.hasKeyword("Enchant Creature")) {
                                            enchantThisType[0] = "Creature";
                                            message[0] = "Select a creature";
                                        } else if (c.hasKeyword("Enchant wall")
                                                || c.hasKeyword("Enchant Wall")) {
                                            enchantThisType[0] = "Wall";
                                            message[0] = "Select a Wall";
                                        } else if (c.hasKeyword("Enchant land you control")
                                                || c.hasKeyword("Enchant Land you control")) {
                                            enchantThisType[0] = "Land.YouCtrl";
                                            message[0] = "Select a land you control";
                                        } else if (c.hasKeyword("Enchant land")
                                                || c.hasKeyword("Enchant Land")) {
                                            enchantThisType[0] = "Land";
                                            message[0] = "Select a land";
                                        } else if (c.hasKeyword("Enchant artifact")
                                                || c.hasKeyword("Enchant Artifact")) {
                                            enchantThisType[0] = "Artifact";
                                            message[0] = "Select an artifact";
                                        } else if (c.hasKeyword("Enchant enchantment")
                                                || c.hasKeyword("Enchant Enchantment")) {
                                            enchantThisType[0] = "Enchantment";
                                            message[0] = "Select an enchantment";
                                        }

                                        CardList allCards = AllZoneUtil.getCardsInPlay();

                                        // Make sure that we were able to match the selected aura with our list of criteria

                                        if (enchantThisType[0] != "" && message[0] != "") {

                                            final CardList choices = allCards.getValidCards(enchantThisType[0], card.getController(), card);
                                            final String msg = message[0];

                                            AllZone.getInputControl().setInput(new Input() {
                                                private static final long serialVersionUID = -6271957194091955059L;

                                                @Override
                                                public void showMessage() {
                                                    AllZone.getDisplay().showMessage(msg);
                                                    ButtonUtil.enableOnlyOK();
                                                }

                                                @Override
                                                public void selectButtonOK() {
                                                    stop();
                                                }

                                                @Override
                                                public void selectCard(Card card, PlayerZone zone) {
                                                    if (choices.contains(card)) {

                                                        if (AllZoneUtil.isCardInPlay(card)) {
                                                            c.enchantCard(card);
                                                            stop();
                                                        }
                                                    }
                                                }//selectCard()
                                            });// Input()

                                        }// if we were able to match the selected aura with our list of criteria
                                    }// If enchantment selected is an aura
                                }// If an enchantment is selected
                            }// If there are enchantments in library

                            card.getController().shuffle();
                        }// If answered yes to may exile
                    }// If player is human

                    // player is the computer
                    else {
                        CardList list = AllZoneUtil.getPlayerCardsInLibrary(AllZone.getComputerPlayer());
                        list = list.filter(new CardListFilter() {
                            public boolean addCard(Card c) {
                                return c.isEnchantment() && !c.isAura();
                            }
                        });

                        if (list.size() > 0) {
                            Card c = CardFactoryUtil.AI_getBestEnchantment(list, card, false);

                            AllZone.getGameAction().moveToPlay(c);
                            if (card.getName().equals("Academy Rector")) {
                                AllZone.getGameAction().exile(card);
                            }
                            card.getController().shuffle();
                        }
                    }// player is the computer
                }// resolve()
            };// ability

            StringBuilder sb = new StringBuilder();
            if (card.getName().equals("Academy Rector")) {
                sb.append("Academy Rector - ").append(card.getController());
                sb.append(" may exile this card and place an enchantment from his library onto the battlefield.");
            } else {
                sb.append("Lost Auramancers - ").append(card.getController());
                sb.append(" may place an enchantment from his library onto the battlefield.");
            }
            ability.setStackDescription(sb.toString());

            final Command destroy = new Command() {
                private static final long serialVersionUID = -4352349741511065318L;

                public void execute() {

                    if (card.getName().equals("Lost Auramancers")
                            && card.getCounters(Counters.TIME) <= 0) {
                        AllZone.getStack().addSimultaneousStackEntry(ability);

                    } else if (card.getName().equals("Academy Rector")) {
                        AllZone.getStack().addSimultaneousStackEntry(ability);

                    }

                }// execute()
            };// Command destroy

            card.addDestroyCommand(destroy);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Deadly Grub")) {
            final Command destroy = new Command() {
                private static final long serialVersionUID = -4352349741511065318L;

                public void execute() {
                    if (card.getCounters(Counters.TIME) <= 0) CardFactoryUtil.makeToken("Insect", "G 6 1 Insect",
                            card.getController(), "G", new String[]{"Creature", "Insect"}, 6, 1, new String[]{"Shroud"});
                }
            };

            card.addDestroyCommand(destroy);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Meddling Mage")) {
            final String[] input = new String[1];
            final Ability ability = new Ability(card, "0") {
                @Override
                public void resolve() {
                    if (card.getController().isHuman()) {
                        input[0] = JOptionPane.showInputDialog(null, "Which card?", "Pick card",
                                JOptionPane.QUESTION_MESSAGE);
                        card.setNamedCard(input[0]);
                    } else {
                        String s = "Ancestral Recall";

                        CardList list = new CardList();
                        list.addAll(AllZoneUtil.getPlayerHand(AllZone.getHumanPlayer()));
                        list.addAll(AllZoneUtil.getPlayerCardsInLibrary(AllZone.getHumanPlayer()));
                        list = list.filter(new CardListFilter() {
                            public boolean addCard(Card c) {
                                return !c.isLand() && !c.isUnCastable();
                            }
                        });

                        if (list.size() > 0) {
                            CardList rare;
                            rare = list;
                            rare = rare.filter(new CardListFilter() {
                                public boolean addCard(Card c) {
                                    return c.getRarity().equals("Rare");
                                }
                            });

                            if (rare.size() > 0) {
                                s = rare.get(CardUtil.getRandomIndex(rare)).getName();
                            } else {
                                Card c = list.get(CardUtil.getRandomIndex(list));
                                //System.out.println(c + " - " + c.getRarity());
                                s = c.getName();
                            }
                        }

                        card.setNamedCard(s);

                    }

                }
            };
            Command comesIntoPlay = new Command() {
                private static final long serialVersionUID = 8485080996453793968L;

                public void execute() {
                    AllZone.getStack().addSimultaneousStackEntry(ability);

                }
            };//Command
            ability.setStackDescription("As Meddling Mage enters the battlefield, name a nonland card.");
            card.addComesIntoPlayCommand(comesIntoPlay);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Iona, Shield of Emeria")) {
            Command comesIntoPlay = new Command() {
                private static final long serialVersionUID = 3331342605626623161L;

                public void execute() {
                    if (card.getController().isHuman()) {

                        String color = "";
                        String[] colors = Constant.Color.Colors;
                        colors[colors.length - 1] = null;

                        Object o = GuiUtils.getChoice("Choose color", colors);
                        color = (String) o;
                        card.setChosenColor(color);
                    } else {
                        CardList list = new CardList();
                        list.addAll(AllZoneUtil.getPlayerCardsInLibrary(AllZone.getHumanPlayer()));
                        list.addAll(AllZoneUtil.getPlayerHand(AllZone.getHumanPlayer()));

                        if (list.size() > 0) {
                            String color = CardFactoryUtil.getMostProminentColor(list);
                            if (!color.equals("")) card.setChosenColor(color);
                            else card.setChosenColor("black");
                        } else {
                            card.setChosenColor("black");
                        }
                    }
                }
            };//Command
            card.addComesIntoPlayCommand(comesIntoPlay);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Singe-Mind Ogre")) {
            final SpellAbility ability = new Ability(card, "0") {
                @Override
                public void resolve() {
                    Player opponent = card.getController().getOpponent();
                    CardList handChoices = AllZoneUtil.getPlayerHand(opponent);
                    if (handChoices.size() > 0) {
                        Card random = CardUtil.getRandom(handChoices.toArray());
                        CardList reveal = new CardList(random);
                        GuiUtils.getChoice("Random card", reveal);
                        opponent.loseLife(CardUtil.getConvertedManaCost(random.getManaCost()), card);
                    }
                }//resolve()
            };
            Command intoPlay = new Command() {

                private static final long serialVersionUID = -4833144157620224716L;

                public void execute() {
                    ability.setStackDescription("When CARDNAME enters the battlefield, target player reveals a card at random from his or her hand, then loses life equal to that card's converted mana cost.");
                    AllZone.getStack().addSimultaneousStackEntry(ability);
                }
            };
            card.addComesIntoPlayCommand(intoPlay);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Kinsbaile Borderguard")) {
            final SpellAbility ability = new Ability(card, "0") {
                @Override
                public void resolve() {
                    card.addCounter(Counters.P1P1, countKithkin());
                    //System.out.println("all counters: " +card.sumAllCounters());
                }//resolve()

                public int countKithkin() {
                    CardList kithkin = AllZoneUtil.getPlayerCardsInPlay(card.getController());
                    kithkin = kithkin.filter(new CardListFilter() {

                        public boolean addCard(Card c) {
                            return (c.isType("Kithkin") || c.hasKeyword("Changeling"))
                                    && !c.equals(card);
                        }

                    });
                    return kithkin.size();

                }
            };
            Command intoPlay = new Command() {
                private static final long serialVersionUID = -7067218066522935060L;

                public void execute() {
                    ability.setStackDescription("Kinsbaile Borderguard enters the battlefield with a +1/+1 counter on it for each other Kithkin you control.");
                    AllZone.getStack().addSimultaneousStackEntry(ability);

                }
            };

            final SpellAbility ability2 = new Ability(card, "0") {
                @Override
                public void resolve() {
                    for (int i = 0; i < card.sumAllCounters(); i++) {
                        makeToken();
                    }
                }//resolve()

                public void makeToken() {
                    CardFactoryUtil.makeToken("Kithkin Soldier", "W 1 1 Kithkin Soldier", card.getController(), "W", new String[]{
                            "Creature", "Kithkin", "Soldier"}, 1, 1, new String[]{""});
                }
            };

            Command destroy = new Command() {
                private static final long serialVersionUID = 304026662487997331L;

                public void execute() {
                    ability2.setStackDescription("When Kinsbaile Borderguard is put into a graveyard from play, put a 1/1 white " +
                            "Kithkin Soldier creature token onto the battlefield for each counter on it.");
                    AllZone.getStack().addSimultaneousStackEntry(ability2);

                }
            };

            card.addComesIntoPlayCommand(intoPlay);
            card.addDestroyCommand(destroy);

        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Arctic Nishoba")) {
            final Ability ability = new Ability(card, "0") {
                @Override
                public void resolve() {
                    int lifeGain = card.getCounters(Counters.AGE) * 2;
                    card.getController().gainLife(lifeGain, card);
                }
            };

            Command destroy = new Command() {
                private static final long serialVersionUID = 1863551466234257411L;

                public void execute() {
                    StringBuilder sb = new StringBuilder();
                    sb.append(card.getName()).append(" - gain 2 life for each age counter on it.");
                    ability.setStackDescription(sb.toString());

                    AllZone.getStack().addSimultaneousStackEntry(ability);

                }
            };//command

            card.addDestroyCommand(destroy);
        }//*************** END ************ END **************************


        //*************** START *********** START ************************** 
        else if (cardName.equals("Kavu Titan")) {
            final SpellAbility kicker = new Spell(card) {
                private static final long serialVersionUID = -1598664196463358630L;

                @Override
                public void resolve() {
                    card.setKicked(true);
                    AllZone.getGameAction().moveToPlay(card);
                }

                @Override
                public boolean canPlay() {
                    return super.canPlay() && AllZone.getPhase().getPlayerTurn().equals(card.getController())
                            && !AllZone.getPhase().getPhase().equals("End of Turn")
                            && !AllZoneUtil.isCardInPlay(card);
                }

            };
            kicker.setKickerAbility(true);
            kicker.setManaCost("3 G G");
            kicker.setAdditionalManaCost("2 G");
            kicker.setDescription("Kicker 2 G");

            StringBuilder sb = new StringBuilder();
            sb.append(card.getName()).append(" - Creature 5/5 (Kicked)");
            kicker.setStackDescription(sb.toString());

            card.addSpellAbility(kicker);

            final Ability ability = new Ability(card, "0") {
                @Override
                public void resolve() {
                    card.addCounter(Counters.P1P1, 3);
                    card.addIntrinsicKeyword("Trample");

                    card.setKicked(false);
                }
            };

            Command commandComes = new Command() {
                private static final long serialVersionUID = -2622859088591798773L;

                public void execute() {
                    if (card.isKicked()) {
                        ability.setStackDescription("Kavu Titan gets 3 +1/+1 counters and gains trample.");
                        AllZone.getStack().addSimultaneousStackEntry(ability);

                    }
                }//execute()
            };//CommandComes

            card.addComesIntoPlayCommand(commandComes);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Gnarlid Pack") || cardName.equals("Apex Hawks") || cardName.equals("Enclave Elite") ||
                cardName.equals("Quag Vampires") || cardName.equals("Skitter of Lizards") ||
                cardName.equals("Joraga Warcaller")) {
            final Ability_Static ability = new Ability_Static(card, "0") {
                @Override
                public void resolve() {
                    card.addCounter(Counters.P1P1, card.getMultiKickerMagnitude());
                    card.setMultiKickerMagnitude(0);
                }
            };
            StringBuilder sb = new StringBuilder();
            sb.append(cardName);
            sb.append(" enters the battlefield with a +1/+1 counter on it for each time it was kicked.");
            ability.setStackDescription(sb.toString());

            final Command comesIntoPlay = new Command() {
                private static final long serialVersionUID = 4245563898487609274L;

                public void execute() {
                    AllZone.getStack().addSimultaneousStackEntry(ability);

                }
            };
            card.addComesIntoPlayCommand(comesIntoPlay);
        }//*************** END ************ END **************************

        
        //*************** START *********** START **************************
        else if (cardName.equals("Storm Entity")) {
            final SpellAbility intoPlay = new Ability(card, "0") {

                @Override
                public boolean canPlayAI() {
                    CardList human = AllZoneUtil.getCreaturesInPlay(AllZone.getHumanPlayer());
                    CardListUtil.sortAttack(human);
                    return (human.get(0).getNetAttack() < Phase.getStormCount() && Phase.getStormCount() > 1);
                }

                @Override
                public void resolve() {
                    for (int i = 0; i < Phase.getStormCount() - 1; i++) {
                        card.addCounter(Counters.P1P1, 1);
                    }
                }
            };//SpellAbility

            Command comesIntoPlay = new Command() {
                private static final long serialVersionUID = -3734151854295L;

                public void execute() {
                    AllZone.getStack().addSimultaneousStackEntry(intoPlay);

                }
            };

            StringBuilder sb = new StringBuilder();
            sb.append(cardName).append(" - enters the battlefield with a +1/+1 counter on it for each other spell played this turn.");
            intoPlay.setStackDescription(sb.toString());

            card.addComesIntoPlayCommand(comesIntoPlay);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Vampire Hexmage")) {
            /*
                * Sacrifice Vampire Hexmage: Remove all counters from target permanent.
                */

            Cost cost = new Cost("Sac<1/CARDNAME>", cardName, true);
            final Target tgt = new Target(card, "Select a permanent", "Permanent".split(","));
            final SpellAbility ability = new Ability_Activated(card, cost, tgt) {
                private static final long serialVersionUID = -5084369399105353155L;

                @Override
                public boolean canPlayAI() {

                    //Dark Depths:
                    CardList list = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer(), "Dark Depths");
                    list = list.filter(new CardListFilter() {
                        public boolean addCard(Card crd) {
                            return crd.getCounters(Counters.ICE) >= 3;
                        }
                    });

                    if (list.size() > 0) {
                        tgt.addTarget(list.get(0));
                        return true;
                    }

                    //Get rid of Planeswalkers:
                    list = AllZoneUtil.getPlayerCardsInPlay(AllZone.getHumanPlayer());
                    list = list.filter(new CardListFilter() {
                        public boolean addCard(Card crd) {
                            return crd.isPlaneswalker() && crd.getCounters(Counters.LOYALTY) >= 5;
                        }
                    });

                    if (list.size() > 0) {
                        tgt.addTarget(list.get(0));
                        return true;
                    }

                    return false;
                }

                @Override
                public void resolve() {
                    final Card c = getTargetCard();
                    for (Counters counter : Counters.values()) {
                        if (c.getCounters(counter) > 0) {
                            c.setCounter(counter, 0, false);
                        }
                    }
                }
            };
            card.addSpellAbility(ability);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Sutured Ghoul")) {
            final int[] numCreatures = new int[1];
            final int[] sumPower = new int[1];
            final int[] sumToughness = new int[1];

            Command intoPlay = new Command() {
                private static final long serialVersionUID = -75234586897814L;

                public void execute() {
                    int intermSumPower, intermSumToughness;
                    intermSumPower = intermSumToughness = 0;
                    CardList creats = AllZoneUtil.getPlayerGraveyard(card.getController());
                    creats = creats.filter(new CardListFilter() {
                        public boolean addCard(Card c) {
                            return c.isCreature() && !c.equals(card);
                        }
                    });

                    if (card.getController().isHuman()) {
                        if (creats.size() > 0) {
                            List<Card> selection = GuiUtils.getChoicesOptional("Select creatures to sacrifice", creats.toArray());

                            numCreatures[0] = selection.size();
                            for (int m = 0; m < selection.size(); m++) {
                                intermSumPower += selection.get(m).getBaseAttack();
                                intermSumToughness += selection.get(m).getBaseDefense();
                                AllZone.getGameAction().exile(selection.get(m));
                            }
                        }

                    }//human
                    else {
                        int count = 0;
                        for (int i = 0; i < creats.size(); i++) {
                            Card c = creats.get(i);
                            if (c.getNetAttack() <= 2 && c.getNetDefense() <= 3) {
                                intermSumPower += c.getBaseAttack();
                                intermSumToughness += c.getBaseDefense();
                                AllZone.getGameAction().exile(c);
                                count++;
                            }
                            //is this needed?
                            AllZone.getComputerBattlefield().updateObservers();
                        }
                        numCreatures[0] = count;
                    }
                    sumPower[0] = intermSumPower;
                    sumToughness[0] = intermSumToughness;
                    card.setBaseAttack(sumPower[0]);
                    card.setBaseDefense(sumToughness[0]);
                }
            };
            // Do not remove SpellAbilities created by AbilityFactory or Keywords.
            card.clearFirstSpell();
            card.addComesIntoPlayCommand(intoPlay);
            card.addSpellAbility(new Spell_Permanent(card) {
                private static final long serialVersionUID = 304885517082977723L;

                @Override
                public boolean canPlayAI() {
                    //get all creatures
                    CardList list = AllZoneUtil.getPlayerGraveyard(AllZone.getComputerPlayer());
                    list = list.filter(AllZoneUtil.creatures);
                    return 0 < list.size();
                }
            });
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Nameless Race")) {
            /*
                * As Nameless Race enters the battlefield, pay any amount of life.
                * The amount you pay can't be more than the total number of white
                * nontoken permanents your opponents control plus the total number
                * of white cards in their graveyards.
                * Nameless Race's power and toughness are each equal to the life
                * paid as it entered the battlefield.
                */
            final SpellAbility ability = new Ability(card, "0") {
                @Override
                public void resolve() {
                    Player player = card.getController();
                    Player opp = player.getOpponent();
                    int max = 0;
                    CardList play = AllZoneUtil.getPlayerCardsInPlay(opp);
                    play = play.filter(AllZoneUtil.nonToken);
                    play = play.filter(AllZoneUtil.white);
                    max += play.size();

                    CardList grave = AllZoneUtil.getPlayerGraveyard(opp);
                    grave = grave.filter(AllZoneUtil.white);
                    max += grave.size();

                    String[] life = new String[max + 1];
                    for (int i = 0; i <= max; i++) {
                        life[i] = String.valueOf(i);
                    }

                    Object o = GuiUtils.getChoice("Nameless Race - pay X life", life);
                    String answer = (String) o;
                    int loseLife = 0;
                    try {
                        loseLife = Integer.parseInt(answer.trim());
                    } catch (NumberFormatException nfe) {
                        System.out.println(card.getName() + " - NumberFormatException: " + nfe.getMessage());
                    }

                    card.setBaseAttack(loseLife);
                    card.setBaseDefense(loseLife);

                    player.loseLife(loseLife, card);
                }//resolve()
            };//SpellAbility

            Command intoPlay = new Command() {
                private static final long serialVersionUID = 931101364538995898L;

                public void execute() {
                    AllZone.getStack().addSimultaneousStackEntry(ability);

                }
            };

            StringBuilder sb = new StringBuilder();
            sb.append(cardName).append(" - pay any amount of life.");
            ability.setStackDescription(sb.toString());

            card.addComesIntoPlayCommand(intoPlay);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Banshee")) {
            /*
                * X, Tap: Banshee deals half X damage, rounded down, to target creature or
                * player, and half X damage, rounded up, to you.
                */

            Cost abCost = new Cost("X T", cardName, true);
            Target tgt = new Target(card, "TgtCP");

            final Ability_Activated ability = new Ability_Activated(card, abCost, tgt) {
                private static final long serialVersionUID = 2755743211116192949L;

                @Override
                public void resolve() {
                    int x = card.getXManaCostPaid();
                    if (getTargetPlayer() == null) {
                        getTargetCard().addDamage((int) Math.floor(x / 2.0), card);
                    } else {
                        getTargetPlayer().addDamage((int) Math.floor(x / 2.0), card);
                    }
                    card.getController().addDamage((int) Math.ceil(x / 2.0), card);
                    card.setXManaCostPaid(0);
                }//resolve()

                @Override
                public boolean canPlayAI() {
                    return false;
                }

            };//SpellAbility

            ability.setDescription("X, tap: " + "Banshee deals half X damage, rounded down, to target creature or player, and half X damage, rounded up, to you.");
            ability.setStackDescription(card.getName() + " - Banshee deals half X damage, rounded down, to target creature or player, and half X damage, rounded up, to you.");
            card.addSpellAbility(ability);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Shapeshifter")) {
            Command intoPlay = new Command() {
                private static final long serialVersionUID = 5447692676152380940L;

                public void execute() {
                    if (!card.isToken()) {  //ugly hack to get around tokens created by Crib Swap
                        int num = 0;
                        if (card.getController().isHuman()) {
                            String[] choices = new String[7];
                            for (int j = 0; j < 7; j++) {
                                choices[j] = "" + j;
                            }
                            String answer = (String) (GuiUtils.getChoiceOptional(
                                    card.getName() + " - Choose a number", choices));
                            num = Integer.parseInt(answer);
                        } else {
                            num = 3;
                        }
                        card.setBaseAttack(num);
                        card.setBaseDefense(7 - num);
                    }
                }
            };

            card.addComesIntoPlayCommand(intoPlay);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Metalworker")) {
            final Cost abCost = new Cost("T", card.getName(), true);

            final SpellAbility ability = new Ability_Activated(card, abCost, null) {
                private static final long serialVersionUID = 6661308920885136284L;

                @Override
                public boolean canPlayAI() {
                    //compy doesn't have a manapool
                    return false;
                }//canPlayAI()

                @Override
                public void resolve() {
                    AllZone.getInputControl().setInput(new Input() {
                        private static final long serialVersionUID = 6150236529653275947L;
                        CardList revealed = new CardList();

                        @Override
                        public void showMessage() {
                            //in case hand is empty, don't do anything
                            if (AllZoneUtil.getPlayerHand(card.getController()).size() == 0) stop();

                            AllZone.getDisplay().showMessage(card.getName() + " - Reveal an artifact.  Revealed " + revealed.size() + " so far.  Click OK when done.");
                            ButtonUtil.enableOnlyOK();
                        }

                        @Override
                        public void selectCard(Card c, PlayerZone zone) {
                            if (zone.is(Constant.Zone.Hand) && c.isArtifact() && !revealed.contains(c)) {
                                revealed.add(c);

                                //in case no more cards in hand to reveal
                                if (revealed.size() == AllZoneUtil.getPlayerHand(card.getController()).size()) done();
                                else
                                    showMessage();
                            }
                        }

                        @Override
                        public void selectButtonOK() {
                            done();
                        }

                        void done() {
                            StringBuilder sb = new StringBuilder();
                            for (Card reveal : revealed) sb.append(reveal.getName() + "\n");
                            JOptionPane.showMessageDialog(null, "Revealed Cards:\n" + sb.toString(), card.getName(), JOptionPane.PLAIN_MESSAGE);
                            //adding mana

                            Ability_Mana abMana = new Ability_Mana(card, "0", "1", 2 * revealed.size()) {
                                private static final long serialVersionUID = -2182129023960978132L;
                            };
                            abMana.setUndoable(false);
                            abMana.produceMana();

                            stop();
                        }
                    });
                }//resolve()
            };//SpellAbility

            ability.setDescription(abCost + "Reveal any number of artifact cards in your hand. Add 2 to your mana pool for each card revealed this way.");
            ability.setStackDescription(cardName + " - Reveal any number of artifact cards in your hand.");
            card.addSpellAbility(ability);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Necratog")) {
            final Command untilEOT = new Command() {
                private static final long serialVersionUID = 6743592637334556854L;

                public void execute() {
                    if (AllZoneUtil.isCardInPlay(card)) {
                        card.addTempAttackBoost(-2);
                        card.addTempDefenseBoost(-2);
                    }
                }
            };

            final SpellAbility ability = new Ability(card, "0") {
                @Override
                public boolean canPlayAI() {
                    return false;
                }

                @Override
                public boolean canPlay() {
                    CardList grave = AllZoneUtil.getPlayerGraveyard(card.getController());
                    grave = grave.filter(AllZoneUtil.creatures);
                    return super.canPlay() && grave.size() > 0;
                }

                @Override
                public void resolve() {
                    if (AllZoneUtil.isCardInPlay(card)) {
                        card.addTempAttackBoost(2);
                        card.addTempDefenseBoost(2);
                        AllZone.getEndOfTurn().addUntil(untilEOT);
                    }
                }
            };

            Input runtime = new Input() {
                private static final long serialVersionUID = 63327418012595048L;
                Card topCreature = null;

                public void showMessage() {

                    PlayerZone grave = AllZone.getZone(Constant.Zone.Graveyard, card.getController());
                    for (int i = grave.size() - 1; i >= 0; i--) {
                        Card c = grave.get(i);
                        if (c.isCreature()) {
                            topCreature = c;
                            break;
                        }
                    }
                    AllZone.getDisplay().showMessage(card.getName() + " - Select OK to exile " + topCreature + ".");
                    ButtonUtil.enableAll();
                }

                public void selectButtonOK() {
                    AllZone.getGameAction().exile(topCreature);
                    AllZone.getStack().add(ability);
                    stop();
                }

                public void selectButtonCancel() {
                    stop();
                }
            };


            ability.setDescription("Exile the top creature card of your graveyard: CARDNAME gets +2/+2 until end of turn.");

            StringBuilder sb = new StringBuilder();
            sb.append(card).append(" gets +2/+2 until end of turn.");
            ability.setStackDescription(sb.toString());
            ability.setBeforePayMana(runtime);
            card.addSpellAbility(ability);
        }//*************** END ************ END **************************


        //*************** START *********** START ************************** 
        else if (cardName.equals("Phyrexian Scuta")) {
            Cost abCost = new Cost("3 B PayLife<3>", cardName, false);
            final SpellAbility kicker = new Spell(card, abCost, null) {
                private static final long serialVersionUID = -6420757044982294960L;

                @Override
                public void resolve() {
                    card.setKicked(true);
                    AllZone.getGameAction().moveToPlay(card);
                    card.addCounterFromNonEffect(Counters.P1P1, 2);
                }

                @Override
                public boolean canPlay() {
                    return super.canPlay() && card.getController().getLife() >= 3;
                }

            };
            kicker.setKickerAbility(true);
            kicker.setManaCost("3 B");
            kicker.setDescription("Kicker - Pay 3 life.");

            StringBuilder sb = new StringBuilder();
            sb.append(card.getName()).append(" - Creature 3/3 (Kicked)");
            kicker.setStackDescription(sb.toString());

            card.addSpellAbility(kicker);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Yosei, the Morning Star")) {
            final CardList targetPerms = new CardList();
            final SpellAbility ability = new Ability(card, "0") {
                @Override
                public void resolve() {
                    Player p = getTargetPlayer();
                    if (p.canTarget(card)) {
                        p.setSkipNextUntap(true);
                        for (Card c : targetPerms) {
                            if (AllZoneUtil.isCardInPlay(c) && CardFactoryUtil.canTarget(card, c)) {
                                c.tap();
                            }
                        }
                    }
                    targetPerms.clear();
                }//resolve()
            };

            final Input targetInput = new Input() {
                private static final long serialVersionUID = -8727869672234802473L;

                @Override
                public void showMessage() {
                    if (targetPerms.size() == 5) done();
                    AllZone.getDisplay().showMessage("Select up to 5 target permanents.  Selected (" + targetPerms.size() + ") so far.  Click OK when done.");
                    ButtonUtil.enableOnlyOK();
                }

                @Override
                public void selectButtonOK() {
                    done();
                }

                private void done() {
                    //here, we add the ability to the stack since it's triggered.
                    StringBuilder sb = new StringBuilder();
                    sb.append(card.getName()).append(" - tap up to 5 permanents target player controls. Target player skips his or her next untap step.");
                    ability.setStackDescription(sb.toString());
                    AllZone.getStack().add(ability);
                    stop();
                }

                @Override
                public void selectCard(Card c, PlayerZone zone) {
                    if (zone.is(Constant.Zone.Battlefield, ability.getTargetPlayer()) && !targetPerms.contains(c)) {
                        if (CardFactoryUtil.canTarget(card, c)) {
                            targetPerms.add(c);
                        }
                    }
                    showMessage();
                }
            };//Input

            final Input playerInput = new Input() {
                private static final long serialVersionUID = 4765535692144126496L;

                @Override
                public void showMessage() {
                    AllZone.getDisplay().showMessage(card.getName() + " - Select target player");
                    ButtonUtil.enableOnlyCancel();
                }

                @Override
                public void selectPlayer(Player p) {
                    if (p.canTarget(card)) {
                        ability.setTargetPlayer(p);
                        stopSetNext(targetInput);
                    }
                }

                @Override
                public void selectButtonCancel() {
                    stop();
                }
            };

            Command destroy = new Command() {
                private static final long serialVersionUID = -3868616119471172026L;

                public void execute() {
                    Player player = card.getController();
                    CardList list = CardFactoryUtil.AI_getHumanCreature(card, true);

                    if (player.isHuman()) AllZone.getInputControl().setInput(playerInput);
                    else if (list.size() != 0) {
                        Card target = CardFactoryUtil.AI_getBestCreature(list);
                        ability.setTargetCard(target);
                        AllZone.getStack().addSimultaneousStackEntry(ability);

                    }
                }//execute()
            };
            card.addDestroyCommand(destroy);
        }
        //*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Phyrexian Dreadnought")) {
            final Player player = card.getController();
            final CardList toSac = new CardList();

            final Ability sacOrSac = new Ability(card, "") {
                @Override
                public void resolve() {
                    if (player.isHuman()) {
                        Input target = new Input() {
                            private static final long serialVersionUID = 2698036349873486664L;

                            @Override
                            public void showMessage() {
                                String toDisplay = cardName + " - Select any number of creatures to sacrifice.  ";
                                toDisplay += "Currently, (" + toSac.size() + ") selected with a total power of: " + getTotalPower();
                                toDisplay += "  Click OK when Done.";
                                AllZone.getDisplay().showMessage(toDisplay);
                                ButtonUtil.enableAll();
                            }

                            @Override
                            public void selectButtonOK() {
                                done();
                            }

                            @Override
                            public void selectButtonCancel() {
                                toSac.clear();
                                AllZone.getGameAction().sacrifice(card);
                                stop();
                            }

                            @Override
                            public void selectCard(Card c, PlayerZone zone) {
                                if (c.isCreature() && zone.is(Constant.Zone.Battlefield, AllZone.getHumanPlayer())
                                        && !toSac.contains(c)) {
                                    toSac.add(c);
                                }
                                showMessage();
                            }//selectCard()

                            private void done() {
                                if (getTotalPower() >= 12) {
                                    for (Card sac : toSac) AllZone.getGameAction().sacrifice(sac);
                                } else {
                                    AllZone.getGameAction().sacrifice(card);
                                }
                                toSac.clear();
                                stop();
                            }
                        };//Input
                        AllZone.getInputControl().setInput(target);
                    }
                }//end resolve

                private int getTotalPower() {
                    int sum = 0;
                    for (Card c : toSac) {
                        sum += c.getNetAttack();
                    }
                    return sum;
                }
            };// end sacOrSac

            final Command comesIntoPlay = new Command() {
                private static final long serialVersionUID = 7680692311339496770L;

                public void execute() {
                    sacOrSac.setStackDescription("When " + cardName + " enters the battlefield, sacrifice it unless you sacrifice any number of creatures with total power 12 or greater.");
                    AllZone.getStack().addSimultaneousStackEntry(sacOrSac);

                }
            };

            card.addComesIntoPlayCommand(comesIntoPlay);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Clone") || cardName.equals("Vesuvan Doppelganger")
                || cardName.equals("Quicksilver Gargantuan")
                || cardName.equals("Jwari Shapeshifter")
                || cardName.equals("Phyrexian Metamorph")) {
            final CardFactory cfact = cf;
            final Card[] copyTarget = new Card[1];
            final Card[] cloned = new Card[1];

            final Command leaves = new Command() {
                private static final long serialVersionUID = 8590474793502538215L;

                public void execute() {
                    //Slight hack if the cloner copies a card with triggers
                    AllZone.getTriggerHandler().removeAllFromCard(cloned[0]);

                    Card orig = cfact.getCard(card.getName(), card.getController());
                    PlayerZone dest = AllZone.getZone(card.getCurrentlyCloningCard());
                    AllZone.getGameAction().moveTo(dest, orig);
                    dest.remove(card.getCurrentlyCloningCard());

                }
            };

            final SpellAbility copy = new Spell(card) {
                private static final long serialVersionUID = 4496978456522751302L;

                @Override
                public void resolve() {
                    if (card.getController().isComputer()) {
                        CardList creatures = AllZoneUtil.getCreaturesInPlay();
                        if (!creatures.isEmpty()) {
                            copyTarget[0] = CardFactoryUtil.AI_getBestCreature(creatures);
                        }
                    }

                    if (copyTarget[0] != null) {
                    	/*
                    	 * This cannot just be copyStats with an addSpellAbility loop from copyTarget[0].
                    	 * Unless we get a copySpellAbility.  Adding the SpellAbility from the
                    	 * source card causes many weird and Bad Things to happen.
                    	 */
                    	try {
                    		cloned[0] = cfact.getCard(copyTarget[0].getName(), card.getController());
                    	}
                    	catch(RuntimeException re) {
                    		//the copyTarget was not found in CardFactory
                    		cloned[0] = CardFactory.copyStats(copyTarget[0]);
                    	}
                        cloned[0].setOwner(card.getController());
                        cloned[0].setController(card.getController());
                        if (cardName.equals("Phyrexian Metamorph")) cloned[0].addType("Artifact");
                        cloned[0].setCloneOrigin(card);
                        cloned[0].addLeavesPlayCommand(leaves);
                        cloned[0].setCloneLeavesPlayCommand(leaves);
                        cloned[0].setCurSetCode(copyTarget[0].getCurSetCode());
                        cloned[0].setImageFilename(copyTarget[0].getImageFilename());
                        if (cardName.equals("Vesuvan Doppelganger")) {
                            cloned[0].addExtrinsicKeyword("At the beginning of your upkeep, you may have this creature become a copy of target creature except it doesn't copy that creature's color. If you do, this creature gains this ability.");
                            cloned[0].addColor("U", cloned[0], false, true);
                        } else if (cardName.equals("Quicksilver Gargantuan")) {
                            cloned[0].setBaseDefense(7);
                            cloned[0].setBaseAttack(7);
                        }

                        //Slight hack in case the cloner copies a card with triggers
                        for (Trigger t : cloned[0].getTriggers()) {
                            AllZone.getTriggerHandler().registerTrigger(t);
                        }

                        AllZone.getGameAction().moveToPlayFromHand(cloned[0]);
                        card.setCurrentlyCloningCard(cloned[0]);
                    }
                }
            };//SpellAbility

            Input runtime = new Input() {
                private static final long serialVersionUID = 7615038074569687330L;

                @Override
                public void showMessage() {
                    String message = "Select a creature ";
                    if (cardName.equals("Phyrexian Metamorph")) message += "or artifact ";
                    message += "on the battlefield";
                    AllZone.getDisplay().showMessage(cardName + " - " + message);
                    ButtonUtil.enableOnlyCancel();
                }

                @Override
                public void selectButtonCancel() {
                    stop();
                }

                @Override
                public void selectCard(Card c, PlayerZone z) {
                    if (z.is(Constant.Zone.Battlefield) &&
                            (c.isCreature() || (cardName.equals("Phyrexian Metamorph") && c.isArtifact()))) {
                        if (cardName.equals("Jwari Shapeshifter") && !c.isType("Ally")) {
                            return;
                        }
                        copyTarget[0] = c;
                        stopSetNext(new Input_PayManaCost(copy));
                    }
                }
            };
            // Do not remove SpellAbilities created by AbilityFactory or Keywords.
            card.clearFirstSpell();
            card.addSpellAbility(copy);
            copy.setStackDescription(cardName + " - enters the battlefield as a copy of selected card.");
            copy.setBeforePayMana(runtime);
        }//*************** END ************ END **************************


        //*************** START ************ START **************************
        else if (cardName.equals("Nebuchadnezzar")) {
            /*
                * X, T: Name a card. Target opponent reveals X cards at random from his or her hand.
                * Then that player discards all cards with that name revealed this way.
                * Activate this ability only during your turn.
                */
            Cost abCost = new Cost("X T", cardName, true);
            Target target = new Target(card, "Select target opponent", "Opponent".split(","));
            Ability_Activated discard = new Ability_Activated(card, abCost, target) {
                private static final long serialVersionUID = 4839778470534392198L;

                @Override
                public void resolve() {
                    //name a card
                    String choice = JOptionPane.showInputDialog(null, "Name a card", cardName, JOptionPane.QUESTION_MESSAGE);
                    CardList hand = AllZoneUtil.getPlayerHand(getTargetPlayer());
                    int numCards = card.getXManaCostPaid();
                    numCards = Math.min(hand.size(), numCards);

                    CardList revealed = new CardList();
                    for (int i = 0; i < numCards; i++) {
                        Card random = CardUtil.getRandom(hand.toArray());
                        revealed.add(random);
                        hand.remove(random);
                    }
                    if (!revealed.isEmpty()) {
                        GuiUtils.getChoice("Revealed at random", revealed.toArray());
                    } else {
                        GuiUtils.getChoice("Revealed at random", new String[]{"Nothing to reveal"});
                    }

                    for (Card c : revealed) {
                        if (c.getName().equals(choice)) c.getController().discard(c, this);
                    }
                }

                @Override
                public boolean canPlayAI() {
                    return false;
                }
            };

            discard.getRestrictions().setPlayerTurn(true);

            StringBuilder sbDesc = new StringBuilder();
            sbDesc.append(abCost).append("Name a card. Target opponent reveals X cards at random from his or her hand. ");
            sbDesc.append("Then that player discards all cards with that name revealed this way. ");
            sbDesc.append("Activate this ability only during your turn.");
            discard.setDescription(sbDesc.toString());

            StringBuilder sbStack = new StringBuilder();
            sbStack.append(cardName).append(" - name a card.");
            discard.setStackDescription(sbStack.toString());

            card.addSpellAbility(discard);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Brass Squire")) {

            Target t2 = new Target(card, "Select target creature you control", "Creature.YouCtrl".split(","));
            final Ability_Sub sub = new Ability_Sub(card, t2) {
                private static final long serialVersionUID = -8926850792424930054L;

                @Override
                public boolean chkAI_Drawback() {
                    return false;
                }

                @Override
                public void resolve() {
                    Card equipment = this.getParent().getTargetCard();
                    Card creature = getTargetCard();
                    if (AllZoneUtil.isCardInPlay(equipment) && AllZoneUtil.isCardInPlay(creature)) {
                        if (CardFactoryUtil.canTarget(card, equipment) && CardFactoryUtil.canTarget(card, creature)) {
                            if (equipment.isEquipping()) {
                                Card equipped = equipment.getEquipping().get(0);
                                if (!equipped.equals(creature)) {
                                    equipment.unEquipCard(equipped);
                                    equipment.equipCard(creature);
                                }
                            } else {
                                equipment.equipCard(getTargetCard());
                            }
                        }
                    }
                }

                @Override
                public boolean doTrigger(boolean b) {
                    return false;
                }
            };

            Cost abCost = new Cost("T", cardName, true);
            Target t1 = new Target(card, "Select target equipment you control", "Equipment.YouCtrl".split(","));
            final Ability_Activated ability = new Ability_Activated(card, abCost, t1) {
                private static final long serialVersionUID = 3818559481920103914L;

                @Override
                public boolean canPlayAI() {
                    return false;
                }

                @Override
                public void resolve() {
                    sub.resolve();
                }
            };
            ability.setSubAbility(sub);
            ability.setStackDescription(cardName + " - Attach target Equipment you control to target creature you control.");
            card.addSpellAbility(ability);
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Gore Vassal")) {
            Cost abCost = new Cost("Sac<1/CARDNAME>", cardName, true);
            final Ability_Activated ability = new Ability_Activated(card, abCost, new Target(card, "TgtC")) {
                private static final long serialVersionUID = 3689290210743241201L;

                @Override
                public boolean canPlayAI() {
                    return false;
                }

                @Override
                public void resolve() {
                    final Card target = getTargetCard();

                    if (AllZoneUtil.isCardInPlay(target) && CardFactoryUtil.canTarget(card, target)) {
                        target.addCounter(Counters.M1M1, 1);
                        if (target.getNetDefense() >= 1) {
                            target.addShield();
                            AllZone.getEndOfTurn().addUntil(new Command() {
                                private static final long serialVersionUID = -3332692040606224591L;

                                public void execute() {
                                    target.resetShield();
                                }
                            });
                        }
                    }
                }//resolve()
            };//SpellAbility

            card.addSpellAbility(ability);
            ability.setDescription(abCost + "Put a -1/-1 counter on target creature. Then if that creature's toughness is 1 or greater, regenerate it.");

            StringBuilder sb = new StringBuilder();
            sb.append(cardName).append(" put a -1/-1 counter on target creature.");
            ability.setStackDescription(sb.toString());
        }//*************** END ************ END **************************


        //*************** START *********** START **************************
        else if (cardName.equals("Orcish Captain")) {
            Cost abCost = new Cost("1", cardName, true);
            Target target = new Target(card, "Select target Orc creature", "Creature.Orc".split(","));
            final Ability_Activated ability = new Ability_Activated(card, abCost, target) {
                private static final long serialVersionUID = 6724781940648179318L;

                @Override
                public boolean canPlayAI() {
                    return false;
                }

                @Override
                public void resolve() {
                    final Card tgt = getTargetCard();
                    final boolean[] win = new boolean[1];
                    if (AllZoneUtil.isCardInPlay(tgt) && CardFactoryUtil.canTarget(card, tgt)) {
                        if (GameActionUtil.flipACoin(card.getController(), card)) {
                            tgt.addTempAttackBoost(2);
                            win[0] = true;
                        } else {
                            tgt.addTempDefenseBoost(-2);
                            win[0] = false;
                        }

                        final Command EOT = new Command() {
                            private static final long serialVersionUID = -7905540871887278236L;

                            public void execute() {
                                if (AllZoneUtil.isCardInPlay(tgt)) {
                                    if (win[0]) {
                                        tgt.addTempAttackBoost(-2);
                                    } else {
                                        tgt.addTempDefenseBoost(2);
                                    }
                                }
                            }
                        };
                        AllZone.getEndOfTurn().addUntil(EOT);

                    }//if (card is in play)
                }//resolve()
            };//SpellAbility
            card.addSpellAbility(ability);
            ability.setDescription(abCost + "Flip a coin. If you win the flip, target Orc creature gets +2/+0 until end of turn. If you lose the flip, it gets -0/-2 until end of turn.");
        }//*************** END ************ END **************************

/*
        //*************** START *********** START **************************
        else if (cardName.equals("Orcish Spy")) {
            Target target = new Target(card, "Select target player", new String[]{"Player"});
            Cost abCost = new Cost("T", cardName, true);
            final Ability_Activated ability = new Ability_Activated(card, abCost, target) {
                private static final long serialVersionUID = -7781215422160018196L;

                @Override
                public void resolve() {
                    final Player player = getTargetPlayer();
                    CardList lib = AllZoneUtil.getPlayerCardsInLibrary(player);
                    CardList toDisplay = new CardList();
                    for (int i = 0; i < 3 && i < lib.size(); i++) {
                        toDisplay.add(lib.get(i));
                    }
                    if (lib.size() > 0) {
                        GuiUtils.getChoice("Top three cards of " + player + "'s library", toDisplay.toArray());
                    } else {
                        StringBuilder sb = new StringBuilder();
                        sb.append(getTargetPlayer()).append("'s library is empty!");
                        javax.swing.JOptionPane.showMessageDialog(null, sb.toString(), "Target player's library", JOptionPane.INFORMATION_MESSAGE);
                    }
                }//resolve()

                @Override
                public boolean canPlayAI() {
                    return false;
                }

            };//SpellAbility

            ability.setDescription(abCost + "Look at the top three cards of target player's library.");
            card.addSpellAbility(ability);
        }//*************** END ************ END **************************
*/

        //*************** START *********** START **************************
        else if (cardName.equals("Awakener Druid")) {
            final long[] timeStamp = {0};

            Trigger myTrig = TriggerHandler.parseTrigger("Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | TriggerDescription$ When CARDNAME enters the battlefield, target Forest becomes a 4/5 green Treefolk creature for as long as CARDNAME is on the battlefield. It's still a land.", card);
            Target myTarget = new Target(card, "Choose target forest.", "Land.Forest".split(","), "1", "1");
            final SpellAbility awaken = new Ability(card, "0") {
                @Override
                public void resolve() {
                    if (!AllZone.getZone(card).is("Battlefield") || getTarget().getTargetCards().size() == 0)
                        return;
                    final Card c = getTarget().getTargetCards().get(0);
                    String[] types = {"Creature", "Treefolk"};
                    String[] keywords = {};
                    timeStamp[0] = CardFactoryUtil.activateManland(c, 4, 5, types, keywords, "G");

                    final Command onleave = new Command() {
                        private static final long serialVersionUID = -6004932214386L;
                        long stamp = timeStamp[0];
                        Card tgt = c;

                        public void execute() {
                            String[] types = {"Creature", "Treefolk"};
                            String[] keywords = {""};
                            CardFactoryUtil.revertManland(tgt, types, keywords, "G", stamp);
                        }
                    };
                    card.addLeavesPlayCommand(onleave);
                }
            };//SpellAbility
            awaken.setTarget(myTarget);

            myTrig.setOverridingAbility(awaken);
            card.addTrigger(myTrig);
        }//*************** END ************ END **************************

        
        //*************** START *********** START **************************
        else if (cardName.equals("Duct Crawler") || cardName.equals("Shrewd Hatchling") || cardName.equals("Spin Engine")) {
            String theCost = "0";
            if (cardName.equals("Duct Crawler"))
                theCost = "1 R";
            else if (cardName.equals("Shrewd Hatchling"))
                theCost = "UR";
            else if (cardName.equals("Spin Engine"))
                theCost = "R";

            StringBuilder keywordBuilder = new StringBuilder("HIDDEN CARDNAME can't block ");
            keywordBuilder.append(card.getName()).append(" (").append(card.getUniqueNumber()).append(")");

            AbilityFactory createAb = new AbilityFactory();
            StringBuilder abilityBuilder = new StringBuilder("AB$Pump | Cost$ ");
            abilityBuilder.append(theCost);
            abilityBuilder.append(" | Tgt$ TgtC | IsCurse$ True | KW$ ");
            abilityBuilder.append(keywordBuilder.toString());
            abilityBuilder.append(" | SpellDescription$ Target creature can't block CARDNAME this turn.");
            SpellAbility myAb = createAb.getAbility(abilityBuilder.toString(), card);

            card.addSpellAbility(myAb);


        }//*************** END ************ END **************************
        
        
        //*************** START *********** START **************************
        else if (cardName.equals("Krovikan Sorcerer")) {
            Cost abCost = new Cost("T Discard<1/Card.Black>", cardName, true);
            final Ability_Activated ability = new Ability_Activated(card, abCost, null) {
                private static final long serialVersionUID = 3689290210743241201L;

                @Override
                public boolean canPlayAI() {
                    return false;
                }

                @Override
                public void resolve() {
                	final Player player = card.getController();
                	if (player.isHuman()) {
                		final CardList n = player.drawCards(2);
                		
                		AllZone.getInputControl().setInput(new Input() {
							private static final long serialVersionUID = -1411038851955251074L;

							@Override
                			public void showMessage() {
                				if(n.isEmpty()) stop();
                				AllZone.getDisplay().showMessage(card+" - discard one of the cards drawn.");
                				ButtonUtil.disableAll();
                			}

                			@Override
                			public void selectCard(Card c, PlayerZone zone) {
                				if (zone.is(Constant.Zone.Hand) && n.contains(c)) {
                					player.discard(c, null);
                					stop();
                				}
                			}
                		});//end Input
                	}
                }//resolve()
            };//SpellAbility

            card.addSpellAbility(ability);
            ability.setDescription("Tap, Discard a black card: " + "Draw two cards, then discard one of them.");

            StringBuilder sb = new StringBuilder();
            sb.append(card).append(" - Draw two cards, then discard one of them.");
            ability.setStackDescription(sb.toString());
        }//*************** END ************ END **************************
        
        
        //***************************************************
        // end of card specific code
        //***************************************************

        if (hasKeyword(card, "Level up") != -1 && hasKeyword(card, "maxLevel") != -1) {
            int n = hasKeyword(card, "Level up");
            int m = hasKeyword(card, "maxLevel");
            if (n != -1) {
                String parse = card.getKeyword().get(n).toString();
                String parseMax = card.getKeyword().get(m).toString();

                card.removeIntrinsicKeyword(parse);
                card.removeIntrinsicKeyword(parseMax);


                String k[] = parse.split(":");
                final String manacost = k[1];

                String l[] = parseMax.split(":");
                final int maxLevel = Integer.parseInt(l[1]);

                final SpellAbility levelUp = new Ability_Activated(card, manacost) {
                    private static final long serialVersionUID = 3998280279949548652L;

                    public void resolve() {
                        card.addCounter(Counters.LEVEL, 1);
                    }

                    public boolean canPlayAI() {
                        // Todo: Improve Level up code
                        return card.getCounters(Counters.LEVEL) < maxLevel;
                    }

                };
                levelUp.getRestrictions().setSorcerySpeed(true);
                card.addSpellAbility(levelUp);

                StringBuilder sbDesc = new StringBuilder();
                sbDesc.append("Level up ").append(manacost).append(" (").append(manacost);
                sbDesc.append(": Put a level counter on this. Level up only as a sorcery.)");
                levelUp.setDescription(sbDesc.toString());

                StringBuilder sbStack = new StringBuilder();
                sbStack.append(card).append(" - put a level counter on this.");
                levelUp.setStackDescription(sbStack.toString());

                card.setLevelUp(true);

            }
        }//level up

        return card;
    }