- Convert Balance to script, Simplify Balancing Act

- Add Restore Balance
- Adding a Balance Effect API
This commit is contained in:
Sol
2013-06-18 00:06:51 +00:00
parent 9996b26eba
commit 7073eb5494
8 changed files with 137 additions and 133 deletions

View File

@@ -10,6 +10,7 @@ import forge.card.ability.ai.AlwaysPlayAi;
import forge.card.ability.ai.AnimateAi;
import forge.card.ability.ai.AnimateAllAi;
import forge.card.ability.ai.AttachAi;
import forge.card.ability.ai.BalanceAi;
import forge.card.ability.ai.BecomesBlockedAi;
import forge.card.ability.ai.BondAi;
import forge.card.ability.ai.CanPlayAsDrawbackAi;
@@ -114,6 +115,7 @@ public enum ApiType {
Animate (AnimateEffect.class, AnimateAi.class),
AnimateAll (AnimateAllEffect.class, AnimateAllAi.class),
Attach (AttachEffect.class, AttachAi.class),
Balance (BalanceEffect.class, BalanceAi.class),
BecomesBlocked (BecomesBlockedEffect.class, BecomesBlockedAi.class),
Bond (BondEffect.class, BondAi.class),
ChangeTargets(ChangeTargetsEffect.class, CannotPlayAi.class),

View File

@@ -0,0 +1,53 @@
package forge.card.ability.ai;
import java.util.List;
import org.apache.commons.lang.math.RandomUtils;
import forge.Card;
import forge.CardLists;
import forge.CardPredicates;
import forge.card.ability.SpellAbilityAi;
import forge.card.spellability.SpellAbility;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
public class BalanceAi extends SpellAbilityAi {
/* (non-Javadoc)
* @see forge.card.ability.SpellAbilityAi#canPlayAI(forge.game.player.Player, forge.card.spellability.SpellAbility)
*/
@Override
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
String logic = sa.getParam("AILogic");
int diff = 0;
// TODO Add support for multiplayer logic
final Player opp = aiPlayer.getOpponent();
final List<Card> humPerms = opp.getCardsIn(ZoneType.Battlefield);
final List<Card> compPerms = aiPlayer.getCardsIn(ZoneType.Battlefield);
if ("BalanceCreaturesAndLands".equals(logic)) {
// Copied over from hardcoded Balance. We should be checking value of the lands/creatures not just counting
diff += CardLists.filter(humPerms, CardPredicates.Presets.LANDS).size() -
CardLists.filter(compPerms, CardPredicates.Presets.LANDS).size();
diff += 1.5 * ( CardLists.filter(humPerms, CardPredicates.Presets.CREATURES).size() -
CardLists.filter(compPerms, CardPredicates.Presets.CREATURES).size());
} else if ("BalancePermanents".equals(logic)) {
// Don't cast if you have to sacrifice permanents
diff += humPerms.size() - compPerms.size();
}
if (diff < 0) {
// Don't sacrifice permanents even if opponent has a ton of cards in hand
return false;
}
final List<Card> humHand = opp.getCardsIn(ZoneType.Hand);
final List<Card> compHand = aiPlayer.getCardsIn(ZoneType.Hand);
diff += 0.5 * (humHand.size() - compHand.size());
// Larger differential == more chance to actually cast this spell
return diff > 2 && RandomUtils.nextInt(100) < diff*10;
}
}

View File

@@ -0,0 +1,61 @@
package forge.card.ability.effects;
import java.util.ArrayList;
import java.util.List;
import forge.Card;
import forge.CardLists;
import forge.card.ability.SpellAbilityEffect;
import forge.card.spellability.SpellAbility;
import forge.game.Game;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
/**
* TODO: Write javadoc for this type.
*
*/
public class BalanceEffect extends SpellAbilityEffect {
/* (non-Javadoc)
* @see forge.card.ability.SpellAbilityEffect#resolve(forge.card.spellability.SpellAbility)
*/
@Override
public void resolve(SpellAbility sa) {
Player activator = sa.getActivatingPlayer();
Card source = sa.getSourceCard();
Game game = activator.getGame();
String valid = sa.hasParam("Valid") ? sa.getParam("Valid") : "Card";
ZoneType zone = sa.hasParam("Zone") ? ZoneType.smartValueOf(sa.getParam("Zone")) : ZoneType.Battlefield;
int min = Integer.MAX_VALUE;
final List<Player> players = game.getPlayers();
final List<List<Card>> validCards = new ArrayList<List<Card>>(players.size());
for(int i = 0; i < players.size(); i++) {
// Find the minimum of each Valid per player
validCards.add(CardLists.getValidCards(players.get(i).getCardsIn(zone), valid, activator, source));
min = Math.min(min, validCards.get(i).size());
}
for(int i = 0; i < players.size(); i++) {
Player p = players.get(i);
int numToBalance = validCards.get(i).size() - min;
if (numToBalance == 0) {
continue;
}
if (zone.equals(ZoneType.Hand)) {
for (Card card : p.getController().chooseCardsToDiscardFrom(p, sa, validCards.get(i), numToBalance, numToBalance)) {
if ( null == card ) continue;
p.discard(card, sa);
}
} else { // Battlefield
for(Card card : p.getController().choosePermanentsToSacrifice(sa, numToBalance, numToBalance, validCards.get(i), valid)) {
if ( null == card ) continue;
game.getAction().sacrifice(card, sa);
}
}
}
}
}

View File

@@ -17,12 +17,9 @@
*/
package forge.card.cardfactory;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import forge.Card;
import forge.CardLists;
import forge.CardPredicates;
import forge.Singletons;
import forge.CardPredicates.Presets;
import forge.card.cost.Cost;
@@ -45,108 +42,6 @@ import forge.gui.input.InputPayManaExecuteCommands;
*/
public class CardFactorySorceries {
private static final void balanceLands(Game game, Spell card) {
int minLands = Integer.MAX_VALUE;
for (Player p : game.getPlayers()) {
int pL = p.getLandsInPlay().size();
if( pL < minLands )
minLands = pL;
}
for (Player p : game.getPlayers()) {
List<Card> l = p.getLandsInPlay();
int sac = l.size() - minLands;
if (sac == 0) {
continue;
}
List<Card> toSac = p.getController().choosePermanentsToSacrifice(card, sac, sac, l, "land(s)");
for( Card crd : toSac )
p.getGame().getAction().sacrifice(crd, card);
}
}
private static final void balanceHands(Game game, Spell spell) {
int min = Integer.MAX_VALUE;
for (Player p : game.getPlayers()) {
min = Math.min(min, p.getZone(ZoneType.Hand).size());
}
for (Player p : game.getPlayers()) {
List<Card> hand = new ArrayList<Card>(p.getCardsIn(ZoneType.Hand));
int sac = hand.size() - min;
if (sac == 0) {
continue;
}
List<Card> toDiscard = p.getController().chooseCardsToDiscardFrom(p, spell, hand, sac, sac); // "Select %d more card(s) to discard"
for (Card c : toDiscard)
p.discard(c, spell);
}
}
private static final void balanceCreatures(Game game, Spell card) {
List<List<Card>> creats = new ArrayList<List<Card>>();
for (Player p : game.getPlayers()) {
creats.add(p.getCreaturesInPlay());
}
int min = Integer.MAX_VALUE;
for (List<Card> h : creats) {
int s = h.size();
min = Math.min(min, s);
}
Iterator<List<Card>> cc = creats.iterator();
for (Player p : game.getPlayers()) {
List<Card> c = cc.next();
int sac = c.size() - min;
if (sac == 0) {
continue;
}
List<Card> toSac = p.getController().choosePermanentsToSacrifice(card, sac, sac, c, "creature(s)");
for( Card crd : toSac )
p.getGame().getAction().sacrifice(crd, card);
}
}
private static final SpellAbility getBalance(final Card card) {
return new Spell(card) {
private static final long serialVersionUID = -5941893280103164961L;
@Override
public void resolve() {
final Game game = this.getActivatingPlayer().getGame();
balanceLands(game, this);
balanceHands(game, this);
balanceCreatures(game, this);
}
@Override
public boolean canPlayAI() {
int diff = 0;
final Player ai = getActivatingPlayer();
final Player opp = ai.getOpponent();
final List<Card> humLand = opp.getLandsInPlay();
final List<Card> compLand = ai.getLandsInPlay();
diff += humLand.size() - compLand.size();
final List<Card> humCreats = opp.getCreaturesInPlay();
List<Card> compCreats = ai.getCreaturesInPlay();
compCreats = CardLists.filter(compCreats, CardPredicates.Presets.CREATURES);
diff += 1.5 * (humCreats.size() - compCreats.size());
final List<Card> humHand = opp.getCardsIn(ZoneType.Hand);
final List<Card> compHand = ai.getCardsIn(ZoneType.Hand);
diff += 0.5 * (humHand.size() - compHand.size());
return diff > 2;
}
};
}
private static final SpellAbility getTransmuteArtifact(final Card card) {
/*
* Sacrifice an artifact. If you do, search your library for an
@@ -219,8 +114,7 @@ public class CardFactorySorceries {
public static void buildCard(final Card card, final String cardName) {
if (cardName.equals("Balance")) { card.addSpellAbility(getBalance(card));
} else if (cardName.equals("Transmute Artifact")) { card.addSpellAbility(getTransmuteArtifact(card));
if (cardName.equals("Transmute Artifact")) { card.addSpellAbility(getTransmuteArtifact(card));
}
} // getCard
}