It is currently 25 Apr 2024, 16:20
   
Text Size

Fix for Flowstone Giant suicide

Moderators: timmermac, Blacksmith, KrazyTheFox, Agetian, friarsol, CCGHQ Admins

Fix for Flowstone Giant suicide

Postby jpb » 09 Jan 2009, 07:17

As Bog Wraith pointed out the computer will kill Flowstone Giant by pumping it to death. To fix this add the this code to the beginning of the SSP_canPlay method in CardFactoryUtil.java. Like so.

Code: Select all
  public static boolean SSP_canPlay(Card card)
  {
    
   //hack so computer doesn't kill Flowstone Giant
   if(Constant.Player.Computer.equals(card.getController()) && card.getName().equals("Flowstone Giant")){
      if(card.getDefense() <= 2){
         return false;
      }
      else{
         return true;
      }
   }
jpb
 
Posts: 132
Joined: 05 Sep 2008, 13:12
Has thanked: 0 time
Been thanked: 0 time

Re: Fix for Flowstone Giant suicide

Postby Rob Cashwalker » 09 Jan 2009, 20:00

The other fix for this is to ditch all the SSP_ code and the pump keyword, in favor of the PTPump, KPump and PTKPump code submitted in this post. I took this into account with the canPlayAI functionality.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Fix for Flowstone Giant suicide

Postby DennisBergkamp » 09 Jan 2009, 20:47

Oh, yeah Rob I've been meaning to ask you... have you tested your custom P/T pump code? I'd be happy to include it into the next version.
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Fix for Flowstone Giant suicide

Postby Rob Cashwalker » 09 Jan 2009, 20:51

DennisBergkamp wrote:Oh, yeah Rob I've been meaning to ask you... have you tested your custom P/T pump code? I'd be happy to include it into the next version.
I haven't personally tested any of my code... I haven't gotten it to run from source, or compile it.

I just follow patterns of known working code....
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Fix for Flowstone Giant suicide

Postby DennisBergkamp » 09 Jan 2009, 21:15

Ahh, alright. No problems, I'll add it in and see if I can get it to work.
I usually test my stuff, but even then there's usually a million bugs in it :roll:

I see this is quite a big task though, since we'd have to update a lot of cards in cards.txt (also new cards added?).
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Fix for Flowstone Giant suicide

Postby Rob Cashwalker » 09 Jan 2009, 21:46

As I went through the CardFactory for the 1/8 beta, I only saw a handful of explicitly coded cards that I had done with the expanded pump keywords....

The SSP_ code was the wrong avenue of attack - it's very simple, but difficult to know where to stick new cards in. The post I linked to should cover almost all cards Forge added with his pump keyword, it should replace all the SSP_ defined cards, and probably has a few extras. It is still not updated for alara, but I'm sure someone else here is helping to keep up with adding newly released cards.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Fix for Flowstone Giant suicide

Postby Chris H. » 09 Jan 2009, 22:35

DennisBergkamp wrote:I see this is quite a big task though, since we'd have to update a lot of cards in cards.txt (also new cards added?).
This is starting to get a little over my head. I guess we would first add Rob's code and release a new beta. At that point someone (me? :roll: ) could slowly go through the cards.txt file and concentrate on updating the existing pump creatures. Once we had a stable cards.txt file with the previous released cards we could have someone(s) add new cards to card.txt and card-pictures.txt.
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: Fix for Flowstone Giant suicide

Postby DennisBergkamp » 10 Jan 2009, 17:26

This is starting to get a little over my head. I guess we would first add Rob's code and release a new beta. At that point someone (me? :roll: ) could slowly go through the cards.txt file and concentrate on updating the existing pump creatures. Once we had a stable cards.txt file with the previous released cards we could have someone(s) add new cards to card.txt and card-pictures.txt.
Exactly, I haven't added Rob's code yet though, I'm still in the process of finishing up some new cards first. After I finish those I'll attempt to add his code in. I've already looked at it, for some of the things it's a little unclear what to replace exactly, but I'll give it a shot.
At that point, yes it would be awesome if someone else could update the cards.txt file :mrgreen:
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Fix for Flowstone Giant suicide

Postby Chris H. » 10 Jan 2009, 19:09

DennisBergkamp wrote:
This is starting to get a little over my head. I guess we would first add Rob's code and release a new beta. At that point someone (me? :roll: ) could slowly go through the cards.txt file and concentrate on updating the existing pump creatures. Once we had a stable cards.txt file with the previous released cards we could have someone(s) add new cards to card.txt and card-pictures.txt.
Exactly, I haven't added Rob's code yet though, I'm still in the process of finishing up some new cards first. After I finish those I'll attempt to add his code in. I've already looked at it, for some of the things it's a little unclear what to replace exactly, but I'll give it a shot.
At that point, yes it would be awesome if someone else could update the cards.txt file :mrgreen:
Your and jpb's current crop of code repairs plus a few new cards will get us to the point where you could release a fairly stable beta. That should keep the people on the sidelines happy.

You and Rob could exchange a few privs about his version of the pump code. At some point Rob's code will be ready for an Alpha release. Rob can let us know if his code would require modifications to the existing cards.txt file.

With the cards.txt file corrected to work with Rob's version of the pump code work could then start on adding additional new cards via the new versions of the pump keyword. I could take a portion of the alphabet. Gando, would you be interested in taking on a slice of this?
User avatar
Chris H.
Forge Moderator
 
Posts: 6320
Joined: 04 Nov 2008, 12:11
Location: Mac OS X Yosemite
Has thanked: 644 times
Been thanked: 643 times

Re: Fix for Flowstone Giant suicide

Postby Rob Cashwalker » 11 Jan 2009, 18:27

The post I referenced should already contain all the self-pump cards that used pump or were defined in SSP_ code. There may have been a few Alara cards added since.

I'll clarify the changes here, based on the source from the 1/8 release:

In CardFactory, replace:
Code: Select all
   // -1 means "Pump" is not found
   // any other int means that "Pump" was found in the Card keyword
   private final int shouldPumpCard(Card c) {
      ArrayList a = c.getKeyword();
      for (int i = 0; i < a.size(); i++)
         if (a.get(i).toString().startsWith("Pump"))
            return i;

      return -1;
   }
with this:
Code: Select all
      //self-targeted power and/or toughness pumping abilities
      //-1 means "PTPump" is not found
      //any other int means that "PTPump" was found in the Card keyword
      private final int shouldPTPumpCard(Card c)
      {
        ArrayList a = c.getKeyword();
        for(int i = 0; i < a.size(); i++)
          if(a.get(i).toString().startsWith("PTPump"))
            return i;

        return -1;
      }
      //same thing, for "KPump" - self-targeted keyword adding abilities
      private final int shouldKPumpCard(Card c)
      {
        ArrayList a = c.getKeyword();
        for (int i = 0; i < a.size(); i++)
          if(a.get(i).toString().startsWith("KPump"))
            return i;

        return -1;
      }
      //same thing, for "PTKPump" - self-targeted power and/or toughness pumping
      //plus keyword adding abilities
      private final int shouldPTKPumpCard(Card c)
      {
        ArrayList a = c.getKeyword();
        for (int i = 0; i < a.size(); i++)
          if(a.get(i).toString().startsWith("PTKPump"))
            return i;

        return -1;
      }
Then replace:
Code: Select all
    //is the card  "self pumper" like Furnance Whelp - this card gets +1/+1 until end of turn?
    //-1 means not found
    while(shouldPumpCard(card) != -1)
    {
      int n = shouldPumpCard(card);
      if(n != -1)
      {
        String parse = card.getKeyword().get(n).toString();
        card.removeKeyword(parse);

        final int attack[] = new int[1];
        final int defense[] = new int[1];

        attack[0] =  Integer.parseInt(parse.substring(8,9));
        defense[0] =  Integer.parseInt(parse.substring(10,11));
        final String manaCost = parse.substring(5,6);


        final Command untilEOT = new Command()
        {
          public void execute()
          {
            if(AllZone.GameAction.isCardInPlay(card))
            {
              card.setAttack(card.getAttack() - attack[0]);
              card.setDefense(card.getDefense() - defense[0]);
            }
          }
        };

        SpellAbility ability = new Ability_Activated(card, manaCost)
        {
          public boolean canPlayAI() {return CardFactoryUtil.AI_doesCreatureAttack(card);}
          public void resolve()
          {
            if(AllZone.GameAction.isCardInPlay(card))
            {
              card.setAttack(card.getAttack() + attack[0]);
              card.setDefense(card.getDefense() + defense[0]);

              AllZone.EndOfTurn.addUntil(untilEOT);
            }
          }
        };
        ability.setDescription(manaCost + " : " +cardName +" gets +" +attack[0] +"/+" +defense[0] +" until end of turn.");
        ability.setStackDescription(cardName +" gets +" +attack[0] +"/+" +defense[0] +" until end of turn.");

        card.addSpellAbility(ability);
      }//if (should pump card)
    }//while - card has more pump keywords - Blistering Dieflyn has two pump keywords
with this:
Code: Select all
      //Creatures with simple, self-targeted mana-activated keyword adding abilities
      //-1 means not found
      while(shouldKPumpCard(card) != -1)
      {
        int n = shouldKPumpCard(card);
        if(n != -1)
        {
          String parse = card.getKeyword().get(n).toString();
          card.removeKeyword(parse);

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

          final String manaCost = k[0].substring(6);
          final String keyword = k[1];

          final Command untilEOT = new Command()
          {
            public void execute()
            {
              if(AllZone.GameAction.isCardInPlay(card))
              {
                card.removeKeyword(keyword);
              }
            }
          };

          SpellAbility ability = new Ability_Activated(card, manaCost)
          {
            public boolean canPlayAI() {return CardFactoryUtil.AI_doesCreatureAttack(card);}
            public boolean canPlay()
            {
                return CardFactoryUtil.canUseAbility(card);
            }
            public void resolve()
            {
              if(AllZone.GameAction.isCardInPlay(card))
              {
                card.addKeyword(keyword);
               
                card.abilityUsed++;

                AllZone.EndOfTurn.addUntil(untilEOT);
              }
            }
          };

          String Desc = new String();
          Desc = cardName + " gains " + keyword + " until end of turn.";

          ability.setDescription(manaCost + " : " + Desc);
          ability.setStackDescription(Desc);

          card.addSpellAbility(ability);
        }//if (should pump card)
      }//while - card has more pump keywords - Blistering Dieflyn has two pump keywords


        //Creatures with simple, self-targeted mana-activated power and/or toughness
        //pumping abilities
        //is the card  "self pumper" like Furnance Whelp - this card gets +1/+1 until end of turn?
        //-1 means not found
        while(shouldPTPumpCard(card) != -1)
        {
          int n = shouldPTPumpCard(card);
          if(n != -1)
          {
            String parse = card.getKeyword().get(n).toString();
            card.removeKeyword(parse);

            final int attack[] = new int[1];
            final int defense[] = new int[1];

            String k[] = parse.split(":");
            String pt[] = k[1].split("/");

            final String manaCost = k[0].substring(7);
            attack[0] = Integer.parseInt(pt[0]);
            defense[0] = Integer.parseInt(pt[1]);

            final Command untilEOT = new Command()
            {
              public void execute()
              {
                if(AllZone.GameAction.isCardInPlay(card))
                {
                  card.setAttack(card.getAttack() - attack[0]);
                  card.setDefense(card.getDefense() - defense[0]);
                }
              }
            };

            SpellAbility ability = new Ability_Activated(card, manaCost)
            {
              public boolean canPlayAI()
              {
                  if (card.getDefense() + defense[0] < 1) // no point if it would kill the creature outright
                      return false;
                  return CardFactoryUtil.AI_doesCreatureAttack(card);
              }
              public boolean canPlay()
              {
                  return CardFactoryUtil.canUseAbility(card);
              }
              public void resolve()
              {
                if(AllZone.GameAction.isCardInPlay(card))
                {
                  card.setAttack(card.getAttack() + attack[0]);
                  card.setDefense(card.getDefense() + defense[0]);
                 
                  card.abilityUsed++;

                  AllZone.EndOfTurn.addUntil(untilEOT);
                }
              }
            };

            String Desc = new String();
            Desc = cardName + " gets ";
            if (attack[0] > 0)
                Desc = Desc + "+" + attack[0];
            else
                Desc = Desc + attack[0];
            Desc = Desc + "/";
            if (defense[0] > 0)
                Desc = Desc + "+" + defense[0];
            else
                Desc = Desc + defense[0];
            Desc = Desc + " until end of turn.";

            ability.setDescription(manaCost + " : " + Desc);
            ability.setStackDescription(Desc);

            card.addSpellAbility(ability);
          }//if (should pump card)
        }//while - card has more pump keywords - Blistering Dieflyn has two pump keywords

        //Creatures with simple, self-targeted mana-activated power and/or toughness
        //pumping plus keyword adding abilities
        //is the card  "self pumper" like Furnance Whelp - this card gets +1/+1 until end of turn?
        //-1 means not found
        while(shouldPTKPumpCard(card) != -1)
        {
          int n = shouldPTKPumpCard(card);
          if(n != -1)
          {
            String parse = card.getKeyword().get(n).toString();
            card.removeKeyword(parse);
     
            final int attack[] = new int[1];
            final int defense[] = new int[1];

            String k[] = parse.split(":");
            String ptk[] = k[1].split("/");

            final String manaCost = k[0].substring(8);

            attack[0] = Integer.parseInt(ptk[0]);
            defense[0] = Integer.parseInt(ptk[1]);
            final String keyword = ptk[2];
     
            final Command untilEOT = new Command()
            {
              public void execute()
              {
                if(AllZone.GameAction.isCardInPlay(card))
                {
                  card.removeKeyword(keyword);
                  card.setAttack(card.getAttack() - attack[0]);
                  card.setDefense(card.getDefense() - defense[0]);

                }
              }
            };
     
            SpellAbility ability = new Ability_Activated(card, manaCost)
            {
              public boolean canPlayAI()
              {
                  if (card.getDefense() + defense[0] < 1) // no point if it would kill the creature outright
                      return false;
                  return CardFactoryUtil.AI_doesCreatureAttack(card);
              }
              public boolean canPlay()
              {
                  return CardFactoryUtil.canUseAbility(card);
              }
              public void resolve()
              {
                if(AllZone.GameAction.isCardInPlay(card))
                {
                  card.addKeyword(keyword);
                  card.setAttack(card.getAttack() + attack[0]);
                  card.setDefense(card.getDefense() + defense[0]);
                 
                  card.abilityUsed++;

                  AllZone.EndOfTurn.addUntil(untilEOT);
                }
              }
            };
     
            String Desc = new String();
            Desc = cardName + " gets ";
            if (attack[0] > 0)
                Desc = Desc + "+" + attack[0];
            else
                Desc = Desc + attack[0];
            Desc = Desc + "/";
            if (defense[0] > 0)
                Desc = Desc + "+" + defense[0];
            else
                Desc = Desc + defense[0];
            Desc = Desc + " and gains " + keyword + " until end of turn.";
     
            ability.setDescription(manaCost + " : " + Desc);
            ability.setStackDescription(Desc);
     
            card.addSpellAbility(ability);
          }//if (should pump card)
        }//while - card has more pump keywords - Blistering Dieflyn has two pump keywords
Remove this section:
Code: Select all
    ///////////////////////////////////////////////////////////////
    //processes the cards in CardFactoryUtil.SSP_CardInList()
    //this is going to be a long method so hold onto your hat

    if(CardFactoryUtil.SSP_CardInList(cardName))
    {
      //basically we are trying to construct an activated ability using SpellAbility
      //then that SpellAbility will be added to the card

      final int attack[] = new int[1];
      final int defense[] = new int[1];
      final String keyword[] = new String[1];

      attack[0] =  CardFactoryUtil.SSP_getPowerBoost(cardName);
      defense[0] =  CardFactoryUtil.SSP_getToughBoost(cardName);
      keyword[0] = CardFactoryUtil.SSP_getKeywordBoost(cardName);

      final Command untilEOT = new Command()
      {
        public void execute()
        {
          if(AllZone.GameAction.isCardInPlay(card))
          {
            card.setAttack(card.getAttack() - attack[0]);
            card.setDefense(card.getDefense() - defense[0]);

            if(keyword[0] != null)
              card.removeKeyword(keyword[0]);
          }
        }
      };

      String manaCost = CardFactoryUtil.SSP_getBoostCost(cardName);
      SpellAbility ability = new Ability_Hand(card, manaCost)
      {
        public boolean canPlay()
        {
          //is this card in play?
          PlayerZone zone = AllZone.getZone(getSourceCard());
          boolean inPlay = zone.is(Constant.Zone.Play, getSourceCard().getController());

          return inPlay && CardFactoryUtil.SSP_canPlay(card);
        }

        public boolean canPlayAI() {return CardFactoryUtil.AI_doesCreatureAttack(card);}
        public void resolve()
        {
          if(AllZone.GameAction.isCardInPlay(card))
          {
            card.setAttack(card.getAttack() + attack[0]);
            card.setDefense(card.getDefense() + defense[0]);

            if(keyword[0] != null)
              card.addKeyword(keyword[0]);

            AllZone.EndOfTurn.addUntil(untilEOT);
          }
        }
      };

      if(keyword[0] != null)
      {
        //card gets keyword until end of turn
        ability.setDescription(manaCost + " : " +cardName +" gets " +keyword[0] +" until end of turn.");
        ability.setStackDescription(cardName +" gets " +keyword[0] +" until end of turn.");
      }
      else
      {
        //card gets +x/+x until end of turn
        ability.setDescription(manaCost + " : " +cardName +" gets " +CardFactoryUtil.getPumpString(attack[0]) +"/" +CardFactoryUtil.getPumpString(defense[0]) +" until end of turn.");
        ability.setStackDescription(cardName +" gets " +CardFactoryUtil.getPumpString(attack[0]) +"/" +CardFactoryUtil.getPumpString(defense[0]) +" until end of turn.");
      }
      card.addSpellAbility(ability);
      return card;
    }//if (CardFactoryUtil.SSP_CardInList(cardName))
Now, in CardFactoryUtil remove:
Code: Select all
  // Simple Self Pumpers (SSP_)
  public final static boolean SSP_CardInList(String cardName)
  {
    return
     (
      cardName.equals("Breathstealer") ||
      cardName.equals("Azimaet Drake") ||
      cardName.equals("Cavern Crawler") ||  cardName.equals("Cobalt Golem") ||
      cardName.equals("Dauthi Mercenary") || cardName.equals("Deeptread Merrow") ||
      cardName.equals("Drake Hatchling") ||
      cardName.equals("Ebony Treefolk") || cardName.equals("Enslaved Scout") ||
      cardName.equals("Fire Drake") ||
      cardName.equals("Flowstone Crusher") || cardName.equals("Flowstone Giant") ||
      cardName.equals("Flowstone Hellion") || cardName.equals("Flowstone Mauler") || cardName.equals("Flowstone Shambler") ||
      cardName.equals("Flowstone Thopter") || cardName.equals("Flowstone Wall") || cardName.equals("Flowstone Wyvern") ||
      cardName.equals("Folk of the Pines") ||
      cardName.equals("Glintwing Invoker") ||
      cardName.equals("Hematite Golem") ||
      cardName.equals("Henge Guardian") ||
      cardName.equals("Hooded Kavu") || cardName.equals("Igneous Golem") ||
      cardName.equals("Kitsune Loreweaver") ||
      cardName.equals("Lionheart Maverick") || cardName.equals("Llanowar Cavalry") ||
      cardName.equals("Malachite Golem") ||
      cardName.equals("Mesa Falcon") ||
      cardName.equals("Patagia Golem") || cardName.equals("Pavel Maliki") || cardName.equals("Pearl Dragon") ||
      cardName.equals("Phyrexian Battleflies") || cardName.equals("Pit Imp") || cardName.equals("Plated Rootwalla") ||
      cardName.equals("River Merfolk") || cardName.equals("Roofstalker Wight") ||
      cardName.equals("Rootwalla") || cardName.equals("Roterothopter") ||
      cardName.equals("Serpentine Kavu") || cardName.equals("Shambling Strider") ||
      cardName.equals("Soltari Crusader") || cardName.equals("Soltari Emissary") || cardName.equals("Spitting Drake") ||
       cardName.equals("Stonewood Invoker") ||
       cardName.equals("Torch Drake") ||
      cardName.equals("Vampire Bats") || cardName.equals("Viashino Grappler") ||
      cardName.equals("Wall of Fire") || cardName.equals("Wall of Lava") ||
      cardName.equals("Wall of Opposition") || cardName.equals("Wall of Water") ||
      cardName.equals("Yavimaya Ancients"));
  } // SSP_CardInList(cardName)

  public static String SSP_getBoostCost(String cardName)
  {
    // W:
    if (cardName.equals("Aven Flock") || cardName.equals("Capashen Templar") || cardName.equals("Honor Guard") ||
        cardName.equals("Kjeldoran Outrider") || cardName.equals("Llanowar Cavalry") || cardName.equals("Loxodon Stalwart") ||
        cardName.equals("Moonwing Moth") || cardName.equals("Soltari Emissary") || cardName.equals("Tower Drake"))
      return "W";

    // U:
    if (cardName.equals("Azimaet Drake") || cardName.equals("Deeptread Merrow") || cardName.equals("Drake Hatchling") ||
        cardName.equals("Killer Whale") || cardName.equals("Manta Riders") || cardName.equals("Sea Spirit") ||
        cardName.equals("Thunder Wall") || cardName.equals("Wall of Water") || cardName.equals("Whiptongue Frog")
       || cardName.equals("River Merfolk"))
      return "U";

    // B:
    if (cardName.equals("Balshan Collaborator") || cardName.equals("Breathstealer") || cardName.equals("Dirtwater Wraith") ||
        cardName.equals("Dungeon Shade") || cardName.equals("Fetid Horror") || cardName.equals("Frozen Shade") ||
        cardName.equals("Hoar Shade") || cardName.equals("Hooded Kavu") || cardName.equals("Looming Shade") ||
        cardName.equals("Nantuko Shade") || cardName.equals("Phyrexian Battleflies") || cardName.equals("Pit Imp") ||
        cardName.equals("Primeval Shambler") || cardName.equals("Undercity Shade") || cardName.equals("Vampire Bats") ||
        cardName.equals("Whispering Shade"))
      return "B";

    // R:
    if (cardName.equals("Angelfire Crusader") || cardName.equals("Cavern Crawler") ||
        cardName.equals("Colos Yearling") || cardName.equals("Fire Drake") || cardName.equals("Firefly") ||
        cardName.equals("Firescreamer") || cardName.equals("Flame Spirit") || cardName.equals("Flamekin Brawler") ||
        cardName.equals("Flowstone Crusher") || cardName.equals("Flowstone Giant") || cardName.equals("Flowstone Mauler") ||
        cardName.equals("Flowstone Shambler") || cardName.equals("Flowstone Wall") || cardName.equals("Flowstone Wyvern") ||
        cardName.equals("Furnace Spirit") || cardName.equals("Furnace Whelp") || cardName.equals("Goblin Balloon Brigade") ||
        cardName.equals("Granite Gargoyle") || cardName.equals("Pygmy Pyrosaur") || cardName.equals("Pyre Charger") ||
        cardName.equals("Ridgeline Rager") || cardName.equals("Serpentine Kavu") || cardName.equals("Shivan Dragon") ||
        cardName.equals("Spitting Drake") || cardName.equals("Steam Spitter") || cardName.equals("Storm Shaman") ||
        cardName.equals("Viashino Slasher") || cardName.equals("Wall of Fire") || cardName.equals("Wall of Lava"))
      return "R";

    // G:
    if (cardName.equals("Killer Bees") || cardName.equals("Viashino Grappler") || cardName.equals("Yavimaya Ancients"))
      return "G";

    // 1:
    if (cardName.equals("Adarkar Sentinel") || cardName.equals("Carrion Ants") || cardName.equals("Flowstone Thopter") ||
        cardName.equals("Wall of Opposition"))
      return "1";

    // 1W:
    if (cardName.equals("Kitsune Loreweaver") || cardName.equals("Mesa Falcon") || cardName.equals("Pearl Dragon") ||
        cardName.equals("Soltari Crusader"))
      return "1 W";

    // 1U:
    if (cardName.equals("Cobalt Golem") || cardName.equals("Roofstalker Wight"))
      return "1 U";

    // 1B:
    if (cardName.equals("Dauthi Mercenary"))
      return "1 B";

    // 1R:
    if (cardName.equals("Greater Forgeling") || cardName.equals("Hematite Golem") || cardName.equals("Torch Drake"))
      return "1 R";

    // 1G:
    if (cardName.equals("Folk of the Pines") || cardName.equals("Malachite Golem") || cardName.equals("Rootwalla"))
      return "1 G";

    // BR:
    if (cardName.equals("Pavel Maliki"))
      return "B R";

    // BG:
    if (cardName.equals("Ebony Treefolk"))
      return "B G";

    // RG:
    if (cardName.equals("Shambling Strider"))
      return "R G";

    // 2:
    if (cardName.equals("Dragon Engine") || cardName.equals("Enslaved Scout") || cardName.equals("Henge Guardian") ||
        cardName.equals("Igneous Golem") || cardName.equals("Roterothopter"))
      return "2";

    // 2G:
    if (cardName.equals("Plated Rootwalla"))
      return "2 G";

    // 3:
    if (cardName.equals("Patagia Golem"))
      return "3";

    // 4W:
    if (cardName.equals("Lionheart Maverick"))
      return "4 W";

    // 7U:
    if (cardName.equals("Glintwing Invoker"))
      return "7 U";

    // 7G:
    if (cardName.equals("Stonewood Invoker"))
      return "7 G";

    return "0";
  } // SSP_getBoostCost(cardName, card)


  public static int SSP_getPowerBoost(String cardName)
  {
    // +1/
    if (cardName.equals("Angelfire Crusader") || cardName.equals("Azimaet Drake") ||
        cardName.equals("Balshan Collaborator") || cardName.equals("Breathstealer") || cardName.equals("Carrion Ants") ||
        cardName.equals("Cavern Crawler") || cardName.equals("Colos Yearling") || cardName.equals("Dauthi Mercenary") ||
        cardName.equals("Dirtwater Wraith") || cardName.equals("Dragon Engine") || cardName.equals("Drake Hatchling") ||
        cardName.equals("Dungeon Shade") || cardName.equals("Ebony Treefolk") || cardName.equals("Fetid Horror") ||
        cardName.equals("Fire Drake") || cardName.equals("Firefly") || cardName.equals("Firescreamer") ||
        cardName.equals("Flame Spirit") || cardName.equals("Flamekin Brawler") || cardName.equals("Flowstone Crusher") ||
        cardName.equals("Flowstone Hellion") || cardName.equals("Flowstone Mauler") || cardName.equals("Flowstone Shambler") ||
        cardName.equals("Flowstone Thopter") || cardName.equals("Flowstone Wall") || cardName.equals("Folk of the Pines") ||
        cardName.equals("Frozen Shade") || cardName.equals("Furnace Spirit") || cardName.equals("Furnace Whelp") ||
        cardName.equals("Hoar Shade") || cardName.equals("Killer Bees") || cardName.equals("Lionheart Maverick") ||
        cardName.equals("Looming Shade") || cardName.equals("Nantuko Shade") || cardName.equals("Pavel Maliki") ||
        cardName.equals("Phyrexian Battleflies") || cardName.equals("Pit Imp") || cardName.equals("Primeval Shambler") ||
        cardName.equals("Pygmy Pyrosaur") || cardName.equals("Pyre Charger") || cardName.equals("Ridgeline Rager") ||
        cardName.equals("Roterothopter") || cardName.equals("Sea Spirit") || cardName.equals("Shambling Strider") ||
        cardName.equals("Shivan Dragon") || cardName.equals("Soltari Crusader") || cardName.equals("Spitting Drake") ||
        cardName.equals("Steam Spitter") || cardName.equals("Storm Shaman") || cardName.equals("Thunder Wall") ||
        cardName.equals("Torch Drake") || cardName.equals("Undercity Shade") || cardName.equals("Vampire Bats") ||
        cardName.equals("Viashino Slasher") || cardName.equals("Wall of Fire") || cardName.equals("Wall of Lava") ||
        cardName.equals("Wall of Opposition") || cardName.equals("Wall of Water") || cardName.equals("Whispering Shade") ||
        cardName.equals("Yavimaya Ancients"))
      return 1;

    // +2/
    if (cardName.equals("Flowstone Giant") || cardName.equals("Flowstone Wyvern") || cardName.equals("Hematite Golem") ||
        cardName.equals("Rootwalla") || cardName.equals("Breathstealer") || cardName.equals("Carrion Ants"))
      return 2;

    // +3
    if (cardName.equals("Glintwing Invoker") || cardName.equals("Greater Forgeling") || cardName.equals("Plated Rootwalla"))
      return 3;

    // +5
    if (cardName.equals("Stonewood Invoker"))
      return 5;

    return 0;
  } // SSP_getPowerBoost(cardName, card)

  public static int SSP_getToughBoost(String cardName)
  {
    // /+1
    if (cardName.equals("Adarkar Sentinel") || cardName.equals("Aven Flock") || cardName.equals("Balshan Collaborator") ||
        cardName.equals("Capashen Templar") || cardName.equals("Carrion Ants") || cardName.equals("Dungeon Shade") ||
        cardName.equals("Ebony Treefolk") || cardName.equals("Fetid Horror") || cardName.equals("Frozen Shade") ||
        cardName.equals("Granite Gargoyle") || cardName.equals("Hoar Shade") || cardName.equals("Honor Guard") ||
        cardName.equals("Killer Bees") || cardName.equals("Kjeldoran Outrider") || cardName.equals("Looming Shade") ||
        cardName.equals("Loxodon Stalwart") || cardName.equals("Mesa Falcon") || cardName.equals("Moonwing Moth") ||
        cardName.equals("Nantuko Shade") || cardName.equals("Pearl Dragon") || cardName.equals("Primeval Shambler") ||
        cardName.equals("Thunder Wall") || cardName.equals("Tower Drake") || cardName.equals("Undercity Shade") ||
        cardName.equals("Wall of Lava") || cardName.equals("Whispering Shade"))
      return 1;

    // /+2
    if (cardName.equals("Lionheart Maverick") || cardName.equals("Rootwalla"))
      return 2;

    // /+3
    if (cardName.equals("Glintwing Invoker") || cardName.equals("Plated Rootwalla"))
      return 3;

    // /+5
    if (cardName.equals("Stonewood Invoker"))
      return 5;

    // /-1
    if (cardName.equals("Breathstealer") || cardName.equals("Cavern Crawler") || cardName.equals("Flowstone Crusher") ||
        cardName.equals("Flowstone Hellion") || cardName.equals("Flowstone Mauler") || cardName.equals("Flowstone Shambler") ||
        cardName.equals("Flowstone Thopter") || cardName.equals("Flowstone Wall") || cardName.equals("Shambling Strider") ||
        cardName.equals("Viashino Slasher"))
      return -1;

    // /-2
    if (cardName.equals("Flowstone Giant") || cardName.equals("Flowstone Wyvern") || cardName.equals("Yavimaya Ancients"))
      return -2;

    // /-3
    if (cardName.equals("Greater Forgeling"))
      return -3;

    return 0;
  } // SSP_getToughBoost(cardName, card)

  public static String SSP_getKeywordBoost(String cardName)
  {
    // Flying
    if (cardName.equals("Cobalt Golem") || cardName.equals("Flowstone Thopter") || cardName.equals("Glintwing Invoker") ||
        cardName.equals("Goblin Balloon Brigade") || cardName.equals("Killer Whale") || cardName.equals("Manta Riders") ||
        cardName.equals("Patagia Golem") || cardName.equals("Roofstalker Wight") || cardName.equals("Roofastalker Wight"))
      return "Flying";

    // Trample
    if (cardName.equals("Henge Guardian") || cardName.equals("Igneous Golem") ||
        cardName.equals("Malachite Golem") || cardName.equals("Viashino Grappler"))
      return "Trample";

    // Fear
    if (cardName.equals("Hooded Kavu"))
      return "Fear";

    // Mountainwalk
    if (cardName.equals("Enslaved Scout") || cardName.equals("River Merfolk"))
      return "Mountainwalk";

    // Islandwalk
    if (cardName.equals("Deeptread Merrow"))
      return "Islandwalk";

    // Vigilance
    if (cardName.equals("Llanowar Cavalry"))
      return "Vigilance";

    // Haste
    if (cardName.equals("Serpentine Kavu"))
      return "Haste";

    // Shadow
    if (cardName.equals("Soltari Emissary"))
      return "Shadow";

    return null;
  } // SSP_getKeywordBoost(cardName, card)
And replace:
Code: Select all
  // Some abilities have use-per-turn limits
  // [0][0] - Number of unique cards being tracked
  // [1+][0] - Unique Number
  // [1+][1] - Last Turn Resolved
  // [1+][2] - Resolutions This Turn
  private static int SSP_TurnCounts[][] = new int[256][2];

  //yes this is more hacky code
  //Object[0] is the cardname
  //Object[1] is the max number of times it can be used per turn
  //Object[1] has to be an Object like Integer and not just an int
  private static Object[][] limitAbility =
  {
    {"Azimaet Drake"    , new Integer(1)},
    {"Drake Hatchling"  , new Integer(1)},
    {"Fire Drake"       , new Integer(1)},
    {"Plated Rootwalla" , new Integer(1)},
    {"Rootwalla"        , new Integer(1)},
    {"Spitting Drake"   , new Integer(1)},

    {"Phyrexian Battleflies"   , new Integer(2)},
    {"Pit Imp"                 , new Integer(2)},
    {"Roterothopter"           , new Integer(2)},
    {"Vampire Bats"            , new Integer(2)},
  };

  public static boolean SSP_canPlay(Card card)
  {
    int found = -1;

    //try to find card name in limitAbility[][]
    for(int i = 0; i < limitAbility.length; i++)
      if(limitAbility[i][0].equals(card.getName()))
        found = i;

    if(found == -1)
      return true;

    //card was found
    if(card.abilityTurnUsed != AllZone.Phase.getTurn())
    {
      card.abilityTurnUsed = AllZone.Phase.getTurn();
      card.abilityUsed = 0;
    }

    card.abilityUsed++;

    Integer check = (Integer) limitAbility[found][1];
    return card.abilityUsed <= check.intValue();
  }//SSP_canPlay(Card card)

  public static boolean SSP_canCreatureUseAbility(String cardName, Card card)
  {
    for (int i=1; i <= SSP_TurnCounts[0][0]; i++)
    {
      if (SSP_TurnCounts[i][0] == card.getUniqueNumber())
        if (SSP_TurnCounts[i][1] == AllZone.Phase.getTurn())
          // once per turn
          if (cardName.equals("Azimaet Drake") || cardName.equals("Drake Hatchling") ||
              cardName.equals("Fire Drake") || cardName.equals("Plated Rootwalla") ||
              cardName.equals("Rootwalla") || cardName.equals("Spitting Drake"))
            return SSP_TurnCounts[i][2] < 1;

          // twice per turn
          if (cardName.equals("Phyrexian Battleflies") || cardName.equals("Pit Imp") ||
              cardName.equals("Roterothopter") || cardName.equals("Vampire Bats"))
            return SSP_TurnCounts[i][2] < 2;
        else
        {
          SSP_TurnCounts[i][2] = 0;
          return true;
        }
      }

      return true;
  }

  public static void SSP_ResolveTurnCount(Card card)
  {
      for (int i = 1; i <= SSP_TurnCounts[0][0]; i++)
      {
        if (SSP_TurnCounts[i][0] == card.getUniqueNumber())
        {
            SSP_TurnCounts[i][1] = AllZone.Phase.getTurn();
            SSP_TurnCounts[i][2]++;
            return;
        }
      }
      SSP_TurnCounts[0][0]++;
      SSP_TurnCounts[SSP_TurnCounts[0][0]][0] = card.getUniqueNumber();
      SSP_TurnCounts[SSP_TurnCounts[0][0]][1] = AllZone.Phase.getTurn();
      SSP_TurnCounts[SSP_TurnCounts[0][0]][2] = 1;
  }
with this:
Code: Select all
      //yes this is more hacky code
      //Object[0] is the cardname
      //Object[1] is the max number of times it can be used per turn
      //Object[1] has to be an Object like Integer and not just an int
      private static Object[][] AbilityLimits =
      {
        {"Azimaet Drake"    , new Integer(1)},
        {"Drake Hatchling"  , new Integer(1)},
        {"Fire Drake"       , new Integer(1)},
        {"Plated Rootwalla" , new Integer(1)},
        {"Rootwalla"        , new Integer(1)},
        {"Spitting Drake"   , new Integer(1)},

        {"Phyrexian Battleflies"   , new Integer(2)},
        {"Pit Imp"                 , new Integer(2)},
        {"Roterothopter"           , new Integer(2)},
        {"Vampire Bats"            , new Integer(2)},
      };

      public static boolean canUseAbility(Card card)
      {
        int found = -1;

        //try to find card name in AbilityLimits[][]
        for(int i = 0; i < AbilityLimits.length; i++)
          if(AbilityLimits[i][0].equals(card.getName()))
            found = i;

        if(found == -1)
          return true;

        //card was found
        if(card.abilityTurnUsed != AllZone.Phase.getTurn())
        {
          card.abilityTurnUsed = AllZone.Phase.getTurn();
          card.abilityUsed = 0;
        }

        Integer check = (Integer) AbilityLimits[found][1];
        return card.abilityUsed <= check.intValue();
      }//canUseAbility(Card card)
That's it for code changes.
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Fix for Flowstone Giant suicide

Postby DennisBergkamp » 14 Jan 2009, 03:59

Rob,

Alright, I replaced all of those but I'm running into a few bugs. As a test case, I used:

Azimaet Drake
2 U
Creature Drake
Play this ability only once each turn.
1/3
Flying
PTPump U:+1/+0

However, when I run compile + run, I get the following error:

Sorry there has been an error.

For Input string :"+1"

You may need to restart this program.
Something goes wrong with the parseInt, I guess. If I change it to:

Azimaet Drake
2 U
Creature Drake
Play this ability only once each turn.
1/3
Flying
PTPump U:1/0

Things run fine, but then once I start playing with a test deck containing Azimaet Drakes, I can pump the card in my hand (I see the two options: "Azimaet Drake - Creature 1/3" and "U: Azimaet Drake gets +1/0 until end of turn." ).
And if I do play the card, I am able to play its pump ability twice each turn (instead of just once).

EDIT: even worse, I'm able to use its ability as many times as I want, if I put the pump on the stack, and respond to it by pumping again.
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Fix for Flowstone Giant suicide

Postby Rob Cashwalker » 14 Jan 2009, 15:29

Java docs on parseInt wrote:public static int parseInt(String s)
throws NumberFormatException

Parses the string argument as a signed decimal integer. The characters in the string must all be decimal digits, except that the first character may be an ASCII minus sign '-' ('\u002D') to indicate a negative value.
OK, so that explains the "+" sign not working. I'm thinking that we should leave the "+" in the keyword notation, but filter it before it gets into parseInt.

Code: Select all
attack[0] = Integer.parseInt(pt[0].replace("+", "");
defense[0] = Integer.parseInt(pt[1].replace("+", "");
The turn counter is updated on resolution... which isn't correct, but it's what made sense, since it's an obvious place in the ability object to put it, and it works for both the computer and the human. The computer is never going to respond to a spell by playing another spell, so I'm wondering if the increment/check can be done like this:

Code: Select all
      Input abCheck = new Input()
      {
        public void showMessage()
        {
          ability.getSourceCard().abilityUsed++;
          if (!CardFactoryUtil.canUseAbility(ability.getSourceCard().card))
          {
              AllZone.Display.showMessage("This ability can't be used.");
              ButtonUtil.enableOnlyCancel();
           }
        }
        public void selectButtonCancel() {stop();}
        }
      };

      ability.setBeforePayMana(abCheck);
But then we'd need to still figure out a way to increment the counter when the computer plays it. Maybe like this?

Code: Select all
   public void resolve()
   {
      if(AllZone.GameAction.isCardInPlay(card))
      {
         card.setAttack(card.getAttack() + attack[0]);
         card.setDefense(card.getDefense() + defense[0]);

         if (AllZone.Phase.getActivePlayer() == Constant.Player.Computer)
                            card.abilityUsed++;

         AllZone.EndOfTurn.addUntil(untilEOT);
      }
   }
I don't have a clue about how to stop it from playing the ability from the hand.....
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Fix for Flowstone Giant suicide

Postby DennisBergkamp » 14 Jan 2009, 16:28

Rob,

Thanks, I'll give these changes a shot. As for disallowing playing the ability when it's in hand, that should be easy:

Code: Select all
public boolean canPlay()
{
      if (CardFactoryUtil.canUseAbility(card) && AllZone.GameAction.isCardInPlay(card))
              return true;
      else
              return false;
}
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Re: Fix for Flowstone Giant suicide

Postby Rob Cashwalker » 14 Jan 2009, 17:02

But look at the explicit implementation of Shivan Dragon. There's no hack there to make sure it doesn't try to play from the hand....
The Force will be with you, Always.
User avatar
Rob Cashwalker
Programmer
 
Posts: 2167
Joined: 09 Sep 2008, 15:09
Location: New York
Has thanked: 5 times
Been thanked: 40 times

Re: Fix for Flowstone Giant suicide

Postby DennisBergkamp » 14 Jan 2009, 17:10

You're right! Very strange, there's not even a canPlay() method in there... so I wonder why I was getting it with Azimaet Drake?
User avatar
DennisBergkamp
AI Programmer
 
Posts: 2602
Joined: 09 Sep 2008, 15:46
Has thanked: 0 time
Been thanked: 0 time

Next

Return to Forge

Who is online

Users browsing this forum: Google [Bot] and 135 guests


Who is online

In total there are 136 users online :: 1 registered, 0 hidden and 135 guests (based on users active over the past 10 minutes)
Most users ever online was 4143 on 23 Jan 2024, 08:21

Users browsing this forum: Google [Bot] and 135 guests

Login Form