mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Merge branch 'manifestChoices' into 'master'
Manifest: add Choices See merge request core-developers/forge!2020
This commit is contained in:
@@ -1,12 +1,17 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
@@ -83,33 +88,18 @@ public class ManifestAi extends SpellAbilityAi {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkApiLogic(final Player ai, final SpellAbility sa) {
|
||||
static boolean shouldManyfest(final Card card, final Player ai, final SpellAbility sa) {
|
||||
final Game game = ai.getGame();
|
||||
if (ComputerUtil.preventRunAwayActivations(sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Library is empty, no Manifest
|
||||
final CardCollectionView library = ai.getCardsIn(ZoneType.Library);
|
||||
if (library.isEmpty())
|
||||
return false;
|
||||
|
||||
// try not to mill himself with Manifest
|
||||
if (library.size() < 5 && !ai.isCardInPlay("Laboratory Maniac")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check to ensure that there are no replacement effects that prevent creatures ETBing from library
|
||||
// (e.g. Grafdigger's Cage)
|
||||
Card topCopy = CardUtil.getLKICopy(library.getFirst());
|
||||
Card topCopy = CardUtil.getLKICopy(card);
|
||||
topCopy.turnFaceDownNoUpdate();
|
||||
topCopy.setManifested(true);
|
||||
|
||||
final Map<String, Object> repParams = Maps.newHashMap();
|
||||
repParams.put("Event", "Moved");
|
||||
repParams.put("Affected", topCopy);
|
||||
repParams.put("Origin", ZoneType.Library);
|
||||
repParams.put("Origin", card.getZone().getZoneType());
|
||||
repParams.put("Destination", ZoneType.Battlefield);
|
||||
repParams.put("Source", sa.getHostCard());
|
||||
List<ReplacementEffect> list = game.getReplacementHandler().getReplacementList(repParams, ReplacementLayer.Other);
|
||||
@@ -117,27 +107,62 @@ public class ManifestAi extends SpellAbilityAi {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the AI can see the top card of the library, check it
|
||||
final Card topCard = library.getFirst();
|
||||
if (topCard.mayPlayerLook(ai)) {
|
||||
if (card.mayPlayerLook(ai)) {
|
||||
// try to avoid manifest a non Permanent
|
||||
if (!topCard.isPermanent())
|
||||
if (!card.isPermanent())
|
||||
return false;
|
||||
|
||||
// do not manifest a card with X in its cost
|
||||
if (topCard.getManaCost().countX() > 0)
|
||||
if (card.getManaCost().countX() > 0)
|
||||
return false;
|
||||
|
||||
// try to avoid manifesting a creature with zero or less thoughness
|
||||
if (topCard.isCreature() && topCard.getNetToughness() <= 0)
|
||||
if (card.isCreature() && card.getNetToughness() <= 0)
|
||||
return false;
|
||||
|
||||
// card has ETBTrigger or ETBReplacement
|
||||
if (topCard.hasETBTrigger(false) || topCard.hasETBReplacement()) {
|
||||
if (card.hasETBTrigger(false) || card.hasETBReplacement()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkApiLogic(final Player ai, final SpellAbility sa) {
|
||||
final Game game = ai.getGame();
|
||||
final Card host = sa.getHostCard();
|
||||
if (ComputerUtil.preventRunAwayActivations(sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sa.hasParam("Choices") || sa.hasParam("ChoiceZone")) {
|
||||
ZoneType choiceZone = ZoneType.Hand;
|
||||
if (sa.hasParam("ChoiceZone")) {
|
||||
choiceZone = ZoneType.smartValueOf(sa.getParam("ChoiceZone"));
|
||||
}
|
||||
CardCollection choices = new CardCollection(game.getCardsIn(choiceZone));
|
||||
if (sa.hasParam("Choices")) {
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), ai, host);
|
||||
}
|
||||
if (choices.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Library is empty, no Manifest
|
||||
final CardCollectionView library = ai.getCardsIn(ZoneType.Library);
|
||||
if (library.isEmpty())
|
||||
return false;
|
||||
|
||||
// try not to mill himself with Manifest
|
||||
if (library.size() < 5 && !ai.isCardInPlay("Laboratory Maniac")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!shouldManyfest(library.getFirst(), ai, sa)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Probably should be a little more discerning on playing during OPPs turn
|
||||
if (SpellAbilityAi.playReusable(ai, sa)) {
|
||||
return true;
|
||||
@@ -152,4 +177,26 @@ public class ManifestAi extends SpellAbilityAi {
|
||||
|
||||
return MyRandom.getRandom().nextFloat() < .8;
|
||||
}
|
||||
|
||||
protected Card chooseSingleCard(final Player ai, final SpellAbility sa, Iterable<Card> options, boolean isOptional, Player targetedPlayer) {
|
||||
if (Iterables.size(options) <= 1) {
|
||||
return Iterables.getFirst(options, null);
|
||||
}
|
||||
CardCollection filtered = CardLists.filter(options, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(Card input) {
|
||||
if (shouldManyfest(input, ai, sa)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!filtered.isEmpty()) {
|
||||
return ComputerUtilCard.getBestAI(filtered);
|
||||
}
|
||||
if (isOptional) {
|
||||
return null;
|
||||
}
|
||||
return Iterables.getFirst(options, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ public class ManifestEffect extends SpellAbilityEffect {
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
final Card source = sa.getHostCard();
|
||||
final Player activator = sa.getActivatingPlayer();
|
||||
final Game game = source.getGame();
|
||||
// Usually a number leaving possibility for X, Sacrifice X land: Manifest X creatures.
|
||||
final int amount = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(source,
|
||||
@@ -28,7 +29,22 @@ public class ManifestEffect extends SpellAbilityEffect {
|
||||
for (final Player p : getTargetPlayers(sa, "DefinedPlayer")) {
|
||||
if (sa.usesTargeting() || p.canBeTargetedBy(sa)) {
|
||||
CardCollection tgtCards;
|
||||
if ("TopOfLibrary".equals(defined)) {
|
||||
if (sa.hasParam("Choices") || sa.hasParam("ChoiceZone")) {
|
||||
ZoneType choiceZone = ZoneType.Hand;
|
||||
if (sa.hasParam("ChoiceZone")) {
|
||||
choiceZone = ZoneType.smartValueOf(sa.getParam("ChoiceZone"));
|
||||
}
|
||||
CardCollection choices = new CardCollection(game.getCardsIn(choiceZone));
|
||||
if (sa.hasParam("Choices")) {
|
||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, source);
|
||||
}
|
||||
if (choices.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String title = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : "Choose cards to manifest ";
|
||||
tgtCards = new CardCollection(activator.getController().chooseEntitiesForEffect(choices, amount, amount, null, sa, title, p));
|
||||
} else if ("TopOfLibrary".equals(defined)) {
|
||||
tgtCards = p.getTopXCardsFromLibrary(amount);
|
||||
} else {
|
||||
tgtCards = getTargetCards(sa);
|
||||
|
||||
5
forge-gui/res/cardsfolder/upcoming/scroll_of_fate.txt
Normal file
5
forge-gui/res/cardsfolder/upcoming/scroll_of_fate.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Name:Scroll of Fate
|
||||
ManaCost:3
|
||||
Types:Artifact
|
||||
A:AB$ Manifest | Cost$ T | Choices$ Card.YouCtrl | ChoiceZone$ Hand | SpellDescription$ Manifest a card from your hand. (Put that card onto the battlefield face down as a 2/2 creature. Turn it face up at any time for its mana cost if it's a creature card.)
|
||||
Oracle:{T}: Manifest a card from your hand. (Put that card onto the battlefield face down as a 2/2 creature. Turn it face up any time for its mana cost if it's a creature card.)
|
||||
Reference in New Issue
Block a user