mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
merge latest trunk
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -11213,6 +11213,7 @@ res/cardsfolder/t/tribal_golem.txt svneol=native#text/plain
|
|||||||
res/cardsfolder/t/tribal_unity.txt -text
|
res/cardsfolder/t/tribal_unity.txt -text
|
||||||
res/cardsfolder/t/tribute_to_hunger.txt -text
|
res/cardsfolder/t/tribute_to_hunger.txt -text
|
||||||
res/cardsfolder/t/tribute_to_the_wild.txt svneol=native#text/plain
|
res/cardsfolder/t/tribute_to_the_wild.txt svneol=native#text/plain
|
||||||
|
res/cardsfolder/t/trickbind.txt -text
|
||||||
res/cardsfolder/t/trickery_charm.txt -text svneol=unset#text/plain
|
res/cardsfolder/t/trickery_charm.txt -text svneol=unset#text/plain
|
||||||
res/cardsfolder/t/tricks_of_the_trade.txt -text
|
res/cardsfolder/t/tricks_of_the_trade.txt -text
|
||||||
res/cardsfolder/t/trickster_mage.txt svneol=native#text/plain
|
res/cardsfolder/t/trickster_mage.txt svneol=native#text/plain
|
||||||
@@ -12295,6 +12296,7 @@ res/cardsfolder/x/xira_arien.txt svneol=native#text/plain
|
|||||||
res/cardsfolder/x/xun_yu_wei_advisor.txt svneol=native#text/plain
|
res/cardsfolder/x/xun_yu_wei_advisor.txt svneol=native#text/plain
|
||||||
res/cardsfolder/y/yamabushis_flame.txt svneol=native#text/plain
|
res/cardsfolder/y/yamabushis_flame.txt svneol=native#text/plain
|
||||||
res/cardsfolder/y/yamabushis_storm.txt -text
|
res/cardsfolder/y/yamabushis_storm.txt -text
|
||||||
|
res/cardsfolder/y/yare.txt -text
|
||||||
res/cardsfolder/y/yavimaya_ancients.txt svneol=native#text/plain
|
res/cardsfolder/y/yavimaya_ancients.txt svneol=native#text/plain
|
||||||
res/cardsfolder/y/yavimaya_ants.txt svneol=native#text/plain
|
res/cardsfolder/y/yavimaya_ants.txt svneol=native#text/plain
|
||||||
res/cardsfolder/y/yavimaya_barbarian.txt svneol=native#text/plain
|
res/cardsfolder/y/yavimaya_barbarian.txt svneol=native#text/plain
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ Ooze Flux
|
|||||||
Simic Manipulator
|
Simic Manipulator
|
||||||
Ashling the Pilgrim
|
Ashling the Pilgrim
|
||||||
Inner-Flame Igniter
|
Inner-Flame Igniter
|
||||||
|
Novijen Sages
|
||||||
|
Trickbind
|
||||||
|
|
||||||
|
|
||||||
New Phenomenons:
|
New Phenomenons:
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ K:Equip 3
|
|||||||
S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddKeyword$ Deathtouch | Description$ Equipped creature has deathtouch. Whenever equipped creature deals combat damage to a player, that player loses half his or her life, rounded up.
|
S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddKeyword$ Deathtouch | Description$ Equipped creature has deathtouch. Whenever equipped creature deals combat damage to a player, that player loses half his or her life, rounded up.
|
||||||
T:Mode$ DamageDone | ValidSource$ Creature.EquippedBy | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigLoseLifeOpp | TriggerDescription$ Whenever equipped creature deals combat damage to a player, that player loses half his or her life, rounded up.
|
T:Mode$ DamageDone | ValidSource$ Creature.EquippedBy | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigLoseLifeOpp | TriggerDescription$ Whenever equipped creature deals combat damage to a player, that player loses half his or her life, rounded up.
|
||||||
SVar:TrigLoseLifeOpp:AB$ LoseLife | Cost$ 0 | Defined$ TriggeredTarget | LifeAmount$ QuietusX | References$ QuietusX
|
SVar:TrigLoseLifeOpp:AB$ LoseLife | Cost$ 0 | Defined$ TriggeredTarget | LifeAmount$ QuietusX | References$ QuietusX
|
||||||
SVar:QuietusX:Count$DefenderLifeTotal/HalfUp
|
SVar:QuietusX:TriggeredTarget$LifeTotal/HalfUp
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/quietus_spike.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/quietus_spike.jpg
|
||||||
Oracle:Equipped creature has deathtouch.\nWhenever equipped creature deals combat damage to a player, that player loses half his or her life, rounded up.\nEquip {3}
|
Oracle:Equipped creature has deathtouch.\nWhenever equipped creature deals combat damage to a player, that player loses half his or her life, rounded up.\nEquip {3}
|
||||||
SetInfo:PC2 Rare
|
SetInfo:PC2 Rare
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Types:Creature Merfolk
|
|||||||
PT:5/5
|
PT:5/5
|
||||||
T:Mode$ Attacks | ValidCard$ Card.Self | DelayedTrigger$ DelTrig | TriggerDescription$ Whenever CARDNAME attacks or blocks, put it on top of its owner<65>s library at end of combat.
|
T:Mode$ Attacks | ValidCard$ Card.Self | DelayedTrigger$ DelTrig | TriggerDescription$ Whenever CARDNAME attacks or blocks, put it on top of its owner<65>s library at end of combat.
|
||||||
T:Mode$ Blocks | ValidCard$ Card.Self | DelayedTrigger$ DelTrig | Secondary$ True | TriggerDescription$ Whenever CARDNAME attacks or blocks, put it on top of its owner<65>s library at end of combat.
|
T:Mode$ Blocks | ValidCard$ Card.Self | DelayedTrigger$ DelTrig | Secondary$ True | TriggerDescription$ Whenever CARDNAME attacks or blocks, put it on top of its owner<65>s library at end of combat.
|
||||||
SVar:DelTrig:Mode$ Phase | Phase$ EndCombat | Execute$ TrigChange | TriggerDescription$ Put CARDNAME on top of its owner<EFBFBD>s library.
|
SVar:DelTrig:Mode$ Phase | Phase$ EndCombat | Execute$ TrigChange | TriggerDescription$ Put CARDNAME on top of its owner's library.
|
||||||
SVar:TrigChange:AB$ChangeZone | Cost$ 0 | Origin$ Battlefield | Destination$ Library | LibraryPosition$ 0 | Defined$ Self
|
SVar:TrigChange:AB$ChangeZone | Cost$ 0 | Origin$ Battlefield | Destination$ Library | LibraryPosition$ 0 | Defined$ Self
|
||||||
SVar:RemAIDeck:True
|
SVar:RemAIDeck:True
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/saprazzan_outrigger.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/saprazzan_outrigger.jpg
|
||||||
|
|||||||
11
res/cardsfolder/t/trickbind.txt
Normal file
11
res/cardsfolder/t/trickbind.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Name:Trickbind
|
||||||
|
ManaCost:1 U
|
||||||
|
Types:Instant
|
||||||
|
K:Split second
|
||||||
|
A:SP$ Counter | Cost$ 1 U | TargetType$ Activated,Triggered | TgtPrompt$ Select target Activated or Triggered Ability | RememberTargets$ True | ValidTgts$ Card | SubAbility$ DBEffect | SpellDescription$ Counter target activated or triggered ability. If a permanent's ability is countered this way, activated abilities of that permanent can't be activated this turn. (Mana abilities can't be targeted.)
|
||||||
|
SVar:DBEffect:DB$ Effect | Name$ Trickbind Effect | StaticAbilities$ STCantBeActivated | RememberObjects$ Remembered | SubAbility$ DBCleanup | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ1
|
||||||
|
SVar:STCantBeActivated:Mode$ CantBeActivated | EffectZone$ Command | ValidCard$ Permanent.IsRemembered
|
||||||
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/trickbind.jpg
|
||||||
|
Oracle:Split second (As long as this spell is on the stack, players can't cast spells or activate abilities that aren't mana abilities.)\nCounter target activated or triggered ability. If a permanent's ability is countered this way, activated abilities of that permanent can't be activated this turn. (Mana abilities can't be targeted.)
|
||||||
|
SetInfo:TSP Rare
|
||||||
8
res/cardsfolder/y/yare.txt
Normal file
8
res/cardsfolder/y/yare.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Yare
|
||||||
|
ManaCost:2 W
|
||||||
|
Types:Instant
|
||||||
|
A:SP$ Pump | Cost$ 2 W | ValidTgts$ Creature.DefenderCtrl | TgtPrompt$ Select target creature defending player controls | NumAtt$ 3 | KW$ HIDDEN CARDNAME can block an additional creature. & HIDDEN CARDNAME can block an additional creature. | SpellDescription$ Target creature defending player controls gets +3/+0 until end of turn. That creature can block up to two additional creatures this turn.
|
||||||
|
SVar:RemAIDeck:True
|
||||||
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/yare.jpg
|
||||||
|
Oracle:Target creature defending player controls gets +3/+0 until end of turn. That creature can block up to two additional creatures this turn.
|
||||||
|
SetInfo:MIR Rare
|
||||||
@@ -4029,7 +4029,7 @@ Battery
|
|||||||
{3}{G}
|
{3}{G}
|
||||||
Sorcery
|
Sorcery
|
||||||
Put a 3/3 green Elephant creature token onto the battlefield.
|
Put a 3/3 green Elephant creature token onto the battlefield.
|
||||||
IN U (x2), TSB S, HOP U
|
IN U, TSB S, HOP U
|
||||||
|
|
||||||
Assault Griffin
|
Assault Griffin
|
||||||
{3}{W}
|
{3}{W}
|
||||||
@@ -57039,7 +57039,7 @@ Suffering
|
|||||||
{3}{R}
|
{3}{R}
|
||||||
Sorcery
|
Sorcery
|
||||||
Destroy target land.
|
Destroy target land.
|
||||||
IN U (x2), DDH U
|
IN U, DDH U
|
||||||
|
|
||||||
Pain Kami
|
Pain Kami
|
||||||
{2}{R}
|
{2}{R}
|
||||||
@@ -76314,7 +76314,7 @@ Malice
|
|||||||
{3}{B}
|
{3}{B}
|
||||||
Instant
|
Instant
|
||||||
Destroy target nonblack creature. It can't be regenerated.
|
Destroy target nonblack creature. It can't be regenerated.
|
||||||
IN U (x2), DDH U
|
IN U, DDH U
|
||||||
|
|
||||||
Spitebellows
|
Spitebellows
|
||||||
{5}{R}
|
{5}{R}
|
||||||
@@ -77073,7 +77073,7 @@ Deliver
|
|||||||
{2}{U}
|
{2}{U}
|
||||||
Instant
|
Instant
|
||||||
Return target permanent to its owner's hand.
|
Return target permanent to its owner's hand.
|
||||||
IN U (x2)
|
IN U
|
||||||
|
|
||||||
Stand Firm
|
Stand Firm
|
||||||
{W}
|
{W}
|
||||||
@@ -90406,7 +90406,7 @@ Wane
|
|||||||
{W}
|
{W}
|
||||||
Instant
|
Instant
|
||||||
Destroy target enchantment.
|
Destroy target enchantment.
|
||||||
IN U (x2), ARC U
|
IN U, ARC U
|
||||||
|
|
||||||
Waxmane Baku
|
Waxmane Baku
|
||||||
{2}{W}
|
{2}{W}
|
||||||
|
|||||||
@@ -6331,12 +6331,10 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("DefenderCtrl")) {
|
} else if (property.startsWith("DefenderCtrl")) {
|
||||||
Combat combat = Singletons.getModel().getGame().getCombat();
|
|
||||||
if (!Singletons.getModel().getGame().getPhaseHandler().inCombat()) {
|
if (!Singletons.getModel().getGame().getPhaseHandler().inCombat()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Player defender = combat.getDefendingPlayerRelatedTo(source);
|
if (!Singletons.getModel().getGame().getCombat().getDefendingPlayerRelatedTo(source).contains(this.getController())) {
|
||||||
if (!this.getController().equals(defender)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (property.startsWith("EnchantedPlayerCtrl")) {
|
} else if (property.startsWith("EnchantedPlayerCtrl")) {
|
||||||
|
|||||||
@@ -246,7 +246,9 @@ public class AbilityUtils {
|
|||||||
return cards;
|
return cards;
|
||||||
}
|
}
|
||||||
|
|
||||||
cards.addAll(list);
|
if (list != null) {
|
||||||
|
cards.addAll(list);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c != null) {
|
if (c != null) {
|
||||||
@@ -853,10 +855,7 @@ public class AbilityUtils {
|
|||||||
players.add(p);
|
players.add(p);
|
||||||
}
|
}
|
||||||
} else if (defined.equals("DefendingPlayer")) {
|
} else if (defined.equals("DefendingPlayer")) {
|
||||||
final Player p = Singletons.getModel().getGame().getCombat().getDefendingPlayerRelatedTo(card);
|
players.addAll(Singletons.getModel().getGame().getCombat().getDefendingPlayerRelatedTo(card));
|
||||||
if (!players.contains(p)) {
|
|
||||||
players.add(p);
|
|
||||||
}
|
|
||||||
} else if (defined.equals("ChosenPlayer")) {
|
} else if (defined.equals("ChosenPlayer")) {
|
||||||
final Player p = card.getChosenPlayer();
|
final Player p = card.getChosenPlayer();
|
||||||
if (!players.contains(p)) {
|
if (!players.contains(p)) {
|
||||||
|
|||||||
@@ -143,9 +143,9 @@ public class DigEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
// Singletons.getModel().getGameAction().revealToCopmuter(top.toArray());
|
// Singletons.getModel().getGameAction().revealToCopmuter(top.toArray());
|
||||||
// - for when it exists
|
// - for when it exists
|
||||||
} else if (choser.isHuman() && !sa.hasParam("NoLooking")) {
|
} else if (!sa.hasParam("NoLooking")) {
|
||||||
// show the user the revealed cards
|
// show the user the revealed cards
|
||||||
GuiChoose.one("Looking at cards from library", top);
|
choser.getController().reveal("Looking at cards from library", top, library.getZoneType(), library.getPlayer());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sa.hasParam("RememberRevealed")) && !sa.hasParam("RevealValid")) {
|
if ((sa.hasParam("RememberRevealed")) && !sa.hasParam("RevealValid")) {
|
||||||
@@ -251,7 +251,7 @@ public class DigEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
for (j = 0; j < changeNum; j++) {
|
for (j = 0; j < changeNum; j++) {
|
||||||
Card chosen = ComputerUtilCard.getBestAI(valid);
|
Card chosen = ComputerUtilCard.getBestAI(valid);
|
||||||
if (sa.getActivatingPlayer().isHuman() && p.isHuman()) {
|
if (sa.getActivatingPlayer().isOpponentOf(choser) && p.isOpponentOf(choser)) {
|
||||||
chosen = ComputerUtilCard.getWorstAI(valid);
|
chosen = ComputerUtilCard.getWorstAI(valid);
|
||||||
}
|
}
|
||||||
if (chosen == null) {
|
if (chosen == null) {
|
||||||
|
|||||||
@@ -1566,12 +1566,6 @@ public class CardFactoryUtil {
|
|||||||
return CardFactoryUtil.doXMath(oppController.getLife(), m, c);
|
return CardFactoryUtil.doXMath(oppController.getLife(), m, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count$DefenderLifeTotal
|
|
||||||
if (sq[0].contains("DefenderLifeTotal")) {
|
|
||||||
Player defender = Singletons.getModel().getGame().getCombat().getDefendingPlayerRelatedTo(c);
|
|
||||||
return CardFactoryUtil.doXMath(defender.getLife(), m, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count$TargetedLifeTotal (targeted player's life total)
|
// Count$TargetedLifeTotal (targeted player's life total)
|
||||||
if (sq[0].contains("TargetedLifeTotal")) {
|
if (sq[0].contains("TargetedLifeTotal")) {
|
||||||
for (final SpellAbility sa : c.getCharacteristics().getSpellAbility()) {
|
for (final SpellAbility sa : c.getCharacteristics().getSpellAbility()) {
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import java.util.List;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.CardLists;
|
|
||||||
import forge.CardPredicates;
|
import forge.CardPredicates;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.card.ability.AbilityFactory;
|
import forge.card.ability.AbilityFactory;
|
||||||
@@ -54,8 +53,6 @@ public class InputMulligan extends Input {
|
|||||||
/** Constant <code>serialVersionUID=-8112954303001155622L</code>. */
|
/** Constant <code>serialVersionUID=-8112954303001155622L</code>. */
|
||||||
private static final long serialVersionUID = -8112954303001155622L;
|
private static final long serialVersionUID = -8112954303001155622L;
|
||||||
|
|
||||||
private static final int AI_MULLIGAN_THRESHOLD = 5;
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public final void showMessage() {
|
public final void showMessage() {
|
||||||
@@ -100,24 +97,13 @@ public class InputMulligan extends Input {
|
|||||||
GameState game = Singletons.getModel().getGame();
|
GameState game = Singletons.getModel().getGame();
|
||||||
|
|
||||||
// Computer mulligan
|
// Computer mulligan
|
||||||
for (Player ai : game.getPlayers()) {
|
for (Player p : game.getPlayers()) {
|
||||||
if (ai.isHuman()) {
|
if (!(p instanceof AIPlayer)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
AIPlayer ai = (AIPlayer) p;
|
||||||
boolean aiTakesMulligan = true;
|
while (ComputerUtil.wantMulligan(ai)) {
|
||||||
|
ai.doMulligan();
|
||||||
// Computer mulligans if there are no cards with converted mana cost of
|
|
||||||
// 0 in its hand
|
|
||||||
while (aiTakesMulligan) {
|
|
||||||
|
|
||||||
final List<Card> handList = ai.getCardsIn(ZoneType.Hand);
|
|
||||||
final boolean hasLittleCmc0Cards = CardLists.getValidCards(handList, "Card.cmcEQ0", ai, null).size() < 2;
|
|
||||||
aiTakesMulligan = (handList.size() > InputMulligan.AI_MULLIGAN_THRESHOLD) && hasLittleCmc0Cards;
|
|
||||||
|
|
||||||
if (aiTakesMulligan) {
|
|
||||||
ai.doMulligan();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +121,7 @@ public class InputMulligan extends Input {
|
|||||||
final String effName = kw.split(":")[1];
|
final String effName = kw.split(":")[1];
|
||||||
|
|
||||||
final SpellAbility effect = AbilityFactory.getAbility(c.getSVar(effName), c);
|
final SpellAbility effect = AbilityFactory.getAbility(c.getSVar(effName), c);
|
||||||
if (GuiDialog.confirm(c, "Use this card's ability?")) {
|
if (GuiDialog.confirm(c, "Use " + c +"'s ability?")) {
|
||||||
// If we ever let the AI memorize cards in the players
|
// If we ever let the AI memorize cards in the players
|
||||||
// hand, this would be a place to do so.
|
// hand, this would be a place to do so.
|
||||||
game.getActionPlay().playSpellAbilityNoStack(p, effect, false);
|
game.getActionPlay().playSpellAbilityNoStack(p, effect, false);
|
||||||
@@ -143,7 +129,7 @@ public class InputMulligan extends Input {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c.getName().startsWith("Leyline of")) {
|
if (c.getName().startsWith("Leyline of")) {
|
||||||
if (GuiDialog.confirm(c, "Use this card's ability?")) {
|
if (GuiDialog.confirm(c, "Use " + c + "'s ability?")) {
|
||||||
ga.moveToPlay(c);
|
ga.moveToPlay(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1334,25 +1334,36 @@ public final class GameActionUtil {
|
|||||||
}
|
}
|
||||||
String newSubSAString = c.getCharacteristics().getIntrinsicAbility().get(0);
|
String newSubSAString = c.getCharacteristics().getIntrinsicAbility().get(0);
|
||||||
newSubSAString = newSubSAString.replace("SP", "DB");
|
newSubSAString = newSubSAString.replace("SP", "DB");
|
||||||
final AbilitySub newSubSA = (AbilitySub) AbilityFactory.getAbility(newSubSAString, source);
|
final AbilitySub newSubSA = (AbilitySub) AbilityFactory.getAbility(newSubSAString, c);
|
||||||
ArrayList<SpellAbility> addSAs = new ArrayList<SpellAbility>();
|
ArrayList<SpellAbility> addSAs = new ArrayList<SpellAbility>();
|
||||||
// Add the subability to all existing variants
|
// Add the subability to all existing variants
|
||||||
for (SpellAbility s : allSAs) {
|
for (SpellAbility s : allSAs) {
|
||||||
|
//create a new spell copy
|
||||||
final SpellAbility newSA = s.copy();
|
final SpellAbility newSA = s.copy();
|
||||||
newSA.setBasicSpell(false);
|
newSA.setBasicSpell(false);
|
||||||
newSA.setPayCosts(combineCosts(newSA, keyword.substring(19)));
|
newSA.setPayCosts(combineCosts(newSA, keyword.substring(19)));
|
||||||
newSA.setManaCost(ManaCost.NO_COST);
|
newSA.setManaCost(ManaCost.NO_COST);
|
||||||
newSA.setDescription(s.getDescription() + " (Splicing " + c + " onto it)");
|
newSA.setDescription(s.getDescription() + " (Splicing " + c + " onto it)");
|
||||||
newSA.addSplicedCards(c);
|
newSA.addSplicedCards(c);
|
||||||
|
|
||||||
|
// copy all subAbilities
|
||||||
SpellAbility child = newSA;
|
SpellAbility child = newSA;
|
||||||
while (child.getSubAbility() != null) {
|
while (child.getSubAbility() != null) {
|
||||||
AbilitySub newChild = child.getSubAbility().getCopy();
|
AbilitySub newChild = child.getSubAbility().getCopy();
|
||||||
child.setSubAbility(newChild);
|
child.setSubAbility(newChild);
|
||||||
newChild.setParent(child);
|
|
||||||
child = newChild;
|
child = newChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//add the spliced ability to the end of the chain
|
||||||
child.setSubAbility(newSubSA);
|
child.setSubAbility(newSubSA);
|
||||||
newSubSA.setParent(child);
|
|
||||||
|
//set correct source and activating player to all the spliced abilities
|
||||||
|
child = newSubSA;
|
||||||
|
while (child != null) {
|
||||||
|
child.setSourceCard(source);
|
||||||
|
child.setActivatingPlayer(s.getActivatingPlayer());
|
||||||
|
child = child.getSubAbility();
|
||||||
|
}
|
||||||
newSAs.add(0, newSA);
|
newSAs.add(0, newSA);
|
||||||
addSAs.add(newSA);
|
addSAs.add(newSA);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1211,4 +1211,15 @@ public class ComputerUtil {
|
|||||||
threatened.addAll(ComputerUtil.predictThreatenedObjects(aiPlayer, saviour, topStack.getSubAbility()));
|
threatened.addAll(ComputerUtil.predictThreatenedObjects(aiPlayer, saviour, topStack.getSubAbility()));
|
||||||
return threatened;
|
return threatened;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Computer mulligans if there are no cards with converted mana cost of
|
||||||
|
// 0 in its hand
|
||||||
|
public static boolean wantMulligan(AIPlayer ai) {
|
||||||
|
final int AI_MULLIGAN_THRESHOLD = 5;
|
||||||
|
|
||||||
|
final List<Card> handList = ai.getCardsIn(ZoneType.Hand);
|
||||||
|
final boolean hasLittleCmc0Cards = CardLists.getValidCards(handList, "Card.cmcEQ0", ai, null).size() < 2;
|
||||||
|
return (handList.size() > AI_MULLIGAN_THRESHOLD) && hasLittleCmc0Cards;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -545,7 +545,8 @@ public class Combat {
|
|||||||
* a {@link forge.Card} object.
|
* a {@link forge.Card} object.
|
||||||
* @return a {@link forge.Player} object.
|
* @return a {@link forge.Player} object.
|
||||||
*/
|
*/
|
||||||
public Player getDefendingPlayerRelatedTo(final Card source) {
|
public List<Player> getDefendingPlayerRelatedTo(final Card source) {
|
||||||
|
List<Player> players = new ArrayList<Player>();
|
||||||
Card attacker = source;
|
Card attacker = source;
|
||||||
if (source.isAura()) {
|
if (source.isAura()) {
|
||||||
attacker = source.getEnchantingCard();
|
attacker = source.getEnchantingCard();
|
||||||
@@ -553,13 +554,21 @@ public class Combat {
|
|||||||
attacker = source.getEquippingCard();
|
attacker = source.getEquippingCard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return the corresponding defender
|
||||||
Player defender = getDefenderPlayerByAttacker(attacker);
|
Player defender = getDefenderPlayerByAttacker(attacker);
|
||||||
if (null == defender) { // too bad, have to choose now
|
if (null != defender) {
|
||||||
// don't have ui, cannot choose - have to getOpponent
|
players.add(defender);
|
||||||
// that's inaccurate. That opponent may be not even a defender
|
return players;
|
||||||
defender = source.getController().getOpponent();
|
|
||||||
}
|
}
|
||||||
return defender;
|
|
||||||
|
// return all defenders
|
||||||
|
List<GameEntity> defenders = this.getDefenders();
|
||||||
|
for (GameEntity ge : defenders) {
|
||||||
|
if (ge instanceof Player) {
|
||||||
|
players.add((Player) ge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return players;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -277,7 +277,10 @@ public class CombatUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String valid = StringUtils.join(walkTypes, ",");
|
String valid = StringUtils.join(walkTypes, ",");
|
||||||
final Player defendingPlayer = Singletons.getModel().getGame().getCombat().getDefendingPlayerRelatedTo(attacker);
|
Player defendingPlayer = attacker.getController().getOpponent();
|
||||||
|
if (attacker.isAttacking()) {
|
||||||
|
defendingPlayer = Singletons.getModel().getGame().getCombat().getDefendingPlayerRelatedTo(attacker).get(0);
|
||||||
|
}
|
||||||
List<Card> defendingLands = defendingPlayer.getCardsIn(ZoneType.Battlefield);
|
List<Card> defendingLands = defendingPlayer.getCardsIn(ZoneType.Battlefield);
|
||||||
for (Card c : defendingLands) {
|
for (Card c : defendingLands) {
|
||||||
if (c.isValid(valid.split(","), defendingPlayer, attacker)) {
|
if (c.isValid(valid.split(","), defendingPlayer, attacker)) {
|
||||||
@@ -1224,7 +1227,7 @@ public class CombatUtil {
|
|||||||
@Override
|
@Override
|
||||||
public void resolve() {
|
public void resolve() {
|
||||||
this.api = ApiType.Sacrifice;
|
this.api = ApiType.Sacrifice;
|
||||||
final Player opponent = Singletons.getModel().getGame().getCombat().getDefendingPlayerRelatedTo(c);
|
final Player opponent = Singletons.getModel().getGame().getCombat().getDefendingPlayerRelatedTo(c).get(0);
|
||||||
//List<Card> list = AbilityUtils.filterListByType(opponent.getCardsIn(ZoneType.Battlefield), "Permanent", this);
|
//List<Card> list = AbilityUtils.filterListByType(opponent.getCardsIn(ZoneType.Battlefield), "Permanent", this);
|
||||||
final List<Card> list = opponent.getCardsIn(ZoneType.Battlefield);
|
final List<Card> list = opponent.getCardsIn(ZoneType.Battlefield);
|
||||||
List<Card> toSac = opponent.getController().choosePermanentsToSacrifice(list, a, this, false, false);
|
List<Card> toSac = opponent.getController().choosePermanentsToSacrifice(list, a, this, false, false);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import forge.game.GameState;
|
|||||||
import forge.game.GameType;
|
import forge.game.GameType;
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,4 +101,7 @@ public abstract class PlayerController {
|
|||||||
|
|
||||||
public abstract List<Card> orderBlockers(Card attacker, List<Card> blockers);
|
public abstract List<Card> orderBlockers(Card attacker, List<Card> blockers);
|
||||||
public abstract List<Card> orderAttackers(Card blocker, List<Card> attackers);
|
public abstract List<Card> orderAttackers(Card blocker, List<Card> attackers);
|
||||||
|
|
||||||
|
/** Shows the card to this player*/
|
||||||
|
public abstract void reveal(String string, List<Card> cards, ZoneType zone, Player owner);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import forge.game.ai.AiInputCommon;
|
|||||||
import forge.game.ai.ComputerUtil;
|
import forge.game.ai.ComputerUtil;
|
||||||
import forge.game.ai.ComputerUtilBlock;
|
import forge.game.ai.ComputerUtilBlock;
|
||||||
import forge.game.ai.ComputerUtilCombat;
|
import forge.game.ai.ComputerUtilCombat;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.GuiChoose;
|
import forge.gui.GuiChoose;
|
||||||
|
|
||||||
|
|
||||||
@@ -219,4 +220,12 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
return ComputerUtilBlock.orderAttackers(blocker, attackers);
|
return ComputerUtilBlock.orderAttackers(blocker, attackers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.game.player.PlayerController#reveal(java.lang.String, java.util.List)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void reveal(String string, List<Card> cards, ZoneType zone, Player owner) {
|
||||||
|
// We don't know how to reveal cards to AI
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import java.util.Map;
|
|||||||
|
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
import forge.GameEntity;
|
import forge.GameEntity;
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
@@ -20,6 +22,7 @@ import forge.deck.DeckSection;
|
|||||||
import forge.game.GameState;
|
import forge.game.GameState;
|
||||||
import forge.game.GameType;
|
import forge.game.GameType;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.GuiChoose;
|
import forge.gui.GuiChoose;
|
||||||
import forge.gui.GuiDialog;
|
import forge.gui.GuiDialog;
|
||||||
import forge.gui.GuiUtils;
|
import forge.gui.GuiUtils;
|
||||||
@@ -274,4 +277,15 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
GuiUtils.setPanelSelection(blocker);
|
GuiUtils.setPanelSelection(blocker);
|
||||||
return GuiChoose.order("Choose Blocking Order", "Damaged First", 0, attackers, null, blocker);
|
return GuiChoose.order("Choose Blocking Order", "Damaged First", 0, attackers, null, blocker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.game.player.PlayerController#reveal(java.lang.String, java.util.List, forge.game.zone.ZoneType, forge.game.player.Player)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void reveal(String string, List<Card> cards, ZoneType zone, Player owner) {
|
||||||
|
String message = string;
|
||||||
|
if ( StringUtils.isBlank(message) )
|
||||||
|
message = String.format("Looking at %s's %s", owner, zone);
|
||||||
|
GuiChoose.oneOrNone(message, cards);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user