mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
Merge branch 'mayPlayLand' into 'master'
May play land See merge request core-developers/forge!415
This commit is contained in:
@@ -1145,15 +1145,14 @@ public class AiController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CardCollection landsWannaPlay = ComputerUtilAbility.getAvailableLandsToPlay(game, player);
|
CardCollection landsWannaPlay = ComputerUtilAbility.getAvailableLandsToPlay(game, player);
|
||||||
CardCollection playBeforeLand = CardLists.filter(player.getCardsIn(ZoneType.Hand), new Predicate<Card>() {
|
CardCollection playBeforeLand = CardLists.filter(
|
||||||
@Override
|
player.getCardsIn(ZoneType.Hand), CardPredicates.hasSVar("PlayBeforeLandDrop")
|
||||||
public boolean apply(Card card) {
|
);
|
||||||
return "true".equalsIgnoreCase(card.getSVar("PlayBeforeLandDrop"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!playBeforeLand.isEmpty()) {
|
if (!playBeforeLand.isEmpty()) {
|
||||||
SpellAbility wantToPlayBeforeLand = chooseSpellAbilityToPlayFromList(ComputerUtilAbility.getSpellAbilities(playBeforeLand, player), false);
|
SpellAbility wantToPlayBeforeLand = chooseSpellAbilityToPlayFromList(
|
||||||
|
ComputerUtilAbility.getSpellAbilities(playBeforeLand, player), false
|
||||||
|
);
|
||||||
if (wantToPlayBeforeLand != null) {
|
if (wantToPlayBeforeLand != null) {
|
||||||
return singleSpellAbilityList(wantToPlayBeforeLand);
|
return singleSpellAbilityList(wantToPlayBeforeLand);
|
||||||
}
|
}
|
||||||
@@ -1163,14 +1162,28 @@ public class AiController {
|
|||||||
landsWannaPlay = filterLandsToPlay(landsWannaPlay);
|
landsWannaPlay = filterLandsToPlay(landsWannaPlay);
|
||||||
Log.debug("Computer " + game.getPhaseHandler().getPhase().nameForUi);
|
Log.debug("Computer " + game.getPhaseHandler().getPhase().nameForUi);
|
||||||
if (landsWannaPlay != null && !landsWannaPlay.isEmpty() && player.canPlayLand(null)) {
|
if (landsWannaPlay != null && !landsWannaPlay.isEmpty() && player.canPlayLand(null)) {
|
||||||
|
// TODO search for other land it might want to play?
|
||||||
Card land = chooseBestLandToPlay(landsWannaPlay);
|
Card land = chooseBestLandToPlay(landsWannaPlay);
|
||||||
if (ComputerUtil.getDamageFromETB(player, land) < player.getLife() || !player.canLoseLife()
|
if (ComputerUtil.getDamageFromETB(player, land) < player.getLife() || !player.canLoseLife()
|
||||||
|| player.cantLoseForZeroOrLessLife() ) {
|
|| player.cantLoseForZeroOrLessLife() ) {
|
||||||
if (!game.getPhaseHandler().is(PhaseType.MAIN1) || !isSafeToHoldLandDropForMain2(land)) {
|
if (!game.getPhaseHandler().is(PhaseType.MAIN1) || !isSafeToHoldLandDropForMain2(land)) {
|
||||||
game.PLAY_LAND_SURROGATE.setHostCard(land);
|
|
||||||
final List<SpellAbility> abilities = Lists.newArrayList();
|
final List<SpellAbility> abilities = Lists.newArrayList();
|
||||||
abilities.add(game.PLAY_LAND_SURROGATE);
|
|
||||||
return abilities;
|
LandAbility la = new LandAbility(land, player, null);
|
||||||
|
if (la.canPlay()) {
|
||||||
|
abilities.add(la);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add mayPlay option
|
||||||
|
for (CardPlayOption o : land.mayPlay(player)) {
|
||||||
|
la = new LandAbility(land, player, o.getAbility());
|
||||||
|
if (la.canPlay()) {
|
||||||
|
abilities.add(la);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!abilities.isEmpty()) {
|
||||||
|
return abilities;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -448,8 +448,10 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
@Override
|
@Override
|
||||||
public void playChosenSpellAbility(SpellAbility sa) {
|
public void playChosenSpellAbility(SpellAbility sa) {
|
||||||
// System.out.println("Playing sa: " + sa);
|
// System.out.println("Playing sa: " + sa);
|
||||||
if (sa == sa.getHostCard().getGame().PLAY_LAND_SURROGATE) {
|
if (sa instanceof LandAbility) {
|
||||||
player.playLand(sa.getHostCard(), false);
|
if (sa.canPlay()) {
|
||||||
|
sa.resolve();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ComputerUtil.handlePlayingSpellAbility(player, sa, game);
|
ComputerUtil.handlePlayingSpellAbility(player, sa, game);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,10 @@ import forge.game.Game;
|
|||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.ability.effects.CharmEffect;
|
import forge.game.ability.effects.CharmEffect;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.cost.Cost;
|
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.Ability;
|
|
||||||
import forge.game.spellability.AbilitySub;
|
import forge.game.spellability.AbilitySub;
|
||||||
|
import forge.game.spellability.LandAbility;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.SpellAbilityCondition;
|
import forge.game.spellability.SpellAbilityCondition;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -115,18 +114,10 @@ public class SpellAbilityPicker {
|
|||||||
printPhaseInfo();
|
printPhaseInfo();
|
||||||
SpellAbility sa = getPlannedSpellAbility(origGameScore, candidateSAs);
|
SpellAbility sa = getPlannedSpellAbility(origGameScore, candidateSAs);
|
||||||
if (sa != null) {
|
if (sa != null) {
|
||||||
return transformSA(sa);
|
return sa;
|
||||||
}
|
}
|
||||||
createNewPlan(origGameScore, candidateSAs);
|
createNewPlan(origGameScore, candidateSAs);
|
||||||
return transformSA(getPlannedSpellAbility(origGameScore, candidateSAs));
|
return getPlannedSpellAbility(origGameScore, candidateSAs);
|
||||||
}
|
|
||||||
|
|
||||||
private SpellAbility transformSA(SpellAbility sa) {
|
|
||||||
if (sa instanceof PlayLandAbility) {
|
|
||||||
game.PLAY_LAND_SURROGATE.setHostCard(sa.getHostCard());
|
|
||||||
return game.PLAY_LAND_SURROGATE;
|
|
||||||
}
|
|
||||||
return sa;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Plan formulatePlanWithPhase(Score origGameScore, List<SpellAbility> candidateSAs, PhaseType phase) {
|
private Plan formulatePlanWithPhase(Score origGameScore, List<SpellAbility> candidateSAs, PhaseType phase) {
|
||||||
@@ -456,20 +447,11 @@ public class SpellAbilityPicker {
|
|||||||
return ComputerUtil.chooseSacrificeType(player, type, ability, ability.getTargetCard(), amount);
|
return ComputerUtil.chooseSacrificeType(player, type, ability, ability.getTargetCard(), amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PlayLandAbility extends Ability {
|
public static class PlayLandAbility extends LandAbility {
|
||||||
public PlayLandAbility(Card land) {
|
public PlayLandAbility(Card land) {
|
||||||
super(null, (Cost) null);
|
super(land);
|
||||||
setHostCard(land);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canPlay() {
|
|
||||||
return true; //if this ability is added anywhere, it can be assumed that land can be played
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void resolve() {
|
|
||||||
throw new RuntimeException("This ability is intended to indicate \"land to play\" choice only");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toUnsuppressedString() { return "Play land " + (getHostCard() != null ? getHostCard().getName() : ""); }
|
public String toUnsuppressedString() { return "Play land " + (getHostCard() != null ? getHostCard().getName() : ""); }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import forge.card.CardStateName;
|
|||||||
import forge.card.CardType.Supertype;
|
import forge.card.CardType.Supertype;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.cost.Cost;
|
|
||||||
import forge.game.event.Event;
|
import forge.game.event.Event;
|
||||||
import forge.game.event.GameEventGameOutcome;
|
import forge.game.event.GameEventGameOutcome;
|
||||||
import forge.game.phase.Phase;
|
import forge.game.phase.Phase;
|
||||||
@@ -38,7 +37,6 @@ import forge.game.phase.PhaseType;
|
|||||||
import forge.game.phase.Untap;
|
import forge.game.phase.Untap;
|
||||||
import forge.game.player.*;
|
import forge.game.player.*;
|
||||||
import forge.game.replacement.ReplacementHandler;
|
import forge.game.replacement.ReplacementHandler;
|
||||||
import forge.game.spellability.Ability;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.SpellAbilityStackInstance;
|
import forge.game.spellability.SpellAbilityStackInstance;
|
||||||
import forge.game.spellability.SpellAbilityView;
|
import forge.game.spellability.SpellAbilityView;
|
||||||
@@ -170,19 +168,6 @@ public class Game {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Ability PLAY_LAND_SURROGATE = new Ability(null, (Cost) null) {
|
|
||||||
@Override
|
|
||||||
public boolean canPlay() {
|
|
||||||
return true; //if this ability is added anywhere, it can be assumed that land can be played
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void resolve() {
|
|
||||||
throw new RuntimeException("This ability is intended to indicate \"land to play\" choice only");
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public String toUnsuppressedString() { return "Play land"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
private final GameEntityCache<Player, PlayerView> playerCache = new GameEntityCache<>();
|
private final GameEntityCache<Player, PlayerView> playerCache = new GameEntityCache<>();
|
||||||
public Player getPlayer(PlayerView playerView) {
|
public Player getPlayer(PlayerView playerView) {
|
||||||
return playerCache.get(playerView);
|
return playerCache.get(playerView);
|
||||||
@@ -247,8 +232,6 @@ public class Game {
|
|||||||
rules = rules0;
|
rules = rules0;
|
||||||
match = match0;
|
match = match0;
|
||||||
|
|
||||||
spabCache.put(PLAY_LAND_SURROGATE.getId(), PLAY_LAND_SURROGATE);
|
|
||||||
|
|
||||||
int highestTeam = -1;
|
int highestTeam = -1;
|
||||||
for (RegisteredPlayer psc : players0) {
|
for (RegisteredPlayer psc : players0) {
|
||||||
// Track highest team number for auto assigning unassigned teams
|
// Track highest team number for auto assigning unassigned teams
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ package forge.game;
|
|||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import forge.card.CardStateName;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.card.mana.ManaCostParser;
|
import forge.card.mana.ManaCostParser;
|
||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
@@ -119,9 +122,32 @@ public final class GameActionUtil {
|
|||||||
public static final List<SpellAbility> getAlternativeCosts(final SpellAbility sa, final Player activator) {
|
public static final List<SpellAbility> getAlternativeCosts(final SpellAbility sa, final Player activator) {
|
||||||
final List<SpellAbility> alternatives = Lists.newArrayList();
|
final List<SpellAbility> alternatives = Lists.newArrayList();
|
||||||
|
|
||||||
final Card source = sa.getHostCard();
|
Card source = sa.getHostCard();
|
||||||
|
final Game game = source.getGame();
|
||||||
|
|
||||||
if (sa.isSpell()) {
|
if (sa.isSpell()) {
|
||||||
|
boolean lkicheck = false;
|
||||||
|
if (sa.hasParam("Bestow") && !source.isBestowed() && !source.isInZone(ZoneType.Battlefield)) {
|
||||||
|
if (!source.isLKI()) {
|
||||||
|
source = CardUtil.getLKICopy(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
source.animateBestow(false);
|
||||||
|
lkicheck = true;
|
||||||
|
} else if (((Spell) sa).isCastFaceDown()) {
|
||||||
|
// need a copy of the card to turn facedown without trigger anything
|
||||||
|
if (!source.isLKI()) {
|
||||||
|
source = CardUtil.getLKICopy(source);
|
||||||
|
}
|
||||||
|
source.setState(CardStateName.FaceDown, false);
|
||||||
|
lkicheck = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lkicheck) {
|
||||||
|
CardCollection preList = new CardCollection(source);
|
||||||
|
game.getAction().checkStaticAbilities(false, Sets.newHashSet(source), preList);
|
||||||
|
}
|
||||||
|
|
||||||
for (CardPlayOption o : source.mayPlay(activator)) {
|
for (CardPlayOption o : source.mayPlay(activator)) {
|
||||||
// non basic are only allowed if PayManaCost is yes
|
// non basic are only allowed if PayManaCost is yes
|
||||||
if (!sa.isBasicSpell() && o.getPayManaCost() == PayManaCost.NO) {
|
if (!sa.isBasicSpell() && o.getPayManaCost() == PayManaCost.NO) {
|
||||||
@@ -186,6 +212,11 @@ public final class GameActionUtil {
|
|||||||
newSA.setDescription(sb.toString());
|
newSA.setDescription(sb.toString());
|
||||||
alternatives.add(newSA);
|
alternatives.add(newSA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset static abilities
|
||||||
|
if (lkicheck) {
|
||||||
|
game.getAction().checkStaticAbilities(false, Sets.newHashSet(), CardCollection.EMPTY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sa.isBasicSpell()) {
|
if (!sa.isBasicSpell()) {
|
||||||
|
|||||||
@@ -5377,9 +5377,19 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
}
|
}
|
||||||
abilities.removeAll(toRemove);
|
abilities.removeAll(toRemove);
|
||||||
|
|
||||||
if (getState(CardStateName.Original).getType().isLand() && player.canPlayLand(this)) {
|
if (getState(CardStateName.Original).getType().isLand()) {
|
||||||
game.PLAY_LAND_SURROGATE.setHostCard(this);
|
LandAbility la = new LandAbility(this, player, null);
|
||||||
abilities.add(game.PLAY_LAND_SURROGATE);
|
if (la.canPlay()) {
|
||||||
|
abilities.add(la);
|
||||||
|
}
|
||||||
|
|
||||||
|
// extra for MayPlay
|
||||||
|
for (CardPlayOption o : this.mayPlay(player)) {
|
||||||
|
la = new LandAbility(this, player, o.getAbility());
|
||||||
|
if (la.canPlay()) {
|
||||||
|
abilities.add(la);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return abilities;
|
return abilities;
|
||||||
|
|||||||
@@ -1644,21 +1644,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
public final boolean playLand(final Card land, final boolean ignoreZoneAndTiming) {
|
public final boolean playLand(final Card land, final boolean ignoreZoneAndTiming) {
|
||||||
// Dakkon Blackblade Avatar will use a similar effect
|
// Dakkon Blackblade Avatar will use a similar effect
|
||||||
if (canPlayLand(land, ignoreZoneAndTiming)) {
|
if (canPlayLand(land, ignoreZoneAndTiming)) {
|
||||||
land.setController(this, 0);
|
this.playLandNoCheck(land);
|
||||||
if (land.isFaceDown()) {
|
|
||||||
land.turnFaceUp();
|
|
||||||
}
|
|
||||||
game.getAction().moveTo(getZone(ZoneType.Battlefield), land, null, new HashMap<String, Object>());
|
|
||||||
|
|
||||||
// play a sound
|
|
||||||
game.fireEvent(new GameEventLandPlayed(this, land));
|
|
||||||
|
|
||||||
// Run triggers
|
|
||||||
final Map<String, Object> runParams = Maps.newHashMap();
|
|
||||||
runParams.put("Card", land);
|
|
||||||
game.getTriggerHandler().runTrigger(TriggerType.LandPlayed, runParams, false);
|
|
||||||
game.getStack().unfreezeStack();
|
|
||||||
addLandPlayedThisTurn();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1666,6 +1652,24 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final void playLandNoCheck(final Card land) {
|
||||||
|
land.setController(this, 0);
|
||||||
|
if (land.isFaceDown()) {
|
||||||
|
land.turnFaceUp();
|
||||||
|
}
|
||||||
|
game.getAction().moveTo(getZone(ZoneType.Battlefield), land, null, new HashMap<String, Object>());
|
||||||
|
|
||||||
|
// play a sound
|
||||||
|
game.fireEvent(new GameEventLandPlayed(this, land));
|
||||||
|
|
||||||
|
// Run triggers
|
||||||
|
final Map<String, Object> runParams = Maps.newHashMap();
|
||||||
|
runParams.put("Card", land);
|
||||||
|
game.getTriggerHandler().runTrigger(TriggerType.LandPlayed, runParams, false);
|
||||||
|
game.getStack().unfreezeStack();
|
||||||
|
addLandPlayedThisTurn();
|
||||||
|
}
|
||||||
|
|
||||||
public final boolean canPlayLand(final Card land) {
|
public final boolean canPlayLand(final Card land) {
|
||||||
return canPlayLand(land, false);
|
return canPlayLand(land, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Forge: Play Magic: the Gathering.
|
||||||
|
* Copyright (C) 2011 Forge Team
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package forge.game.spellability;
|
||||||
|
|
||||||
|
import forge.game.Game;
|
||||||
|
import forge.game.card.Card;
|
||||||
|
import forge.game.cost.Cost;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.staticability.StaticAbility;
|
||||||
|
import forge.game.zone.Zone;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
|
public class LandAbility extends Ability {
|
||||||
|
|
||||||
|
public LandAbility(Card sourceCard, Player p, StaticAbility mayPlay) {
|
||||||
|
super(sourceCard, (Cost)null);
|
||||||
|
setActivatingPlayer(p);
|
||||||
|
setMayPlay(mayPlay);
|
||||||
|
}
|
||||||
|
public LandAbility(Card sourceCard) {
|
||||||
|
this(sourceCard, sourceCard.getController(), (StaticAbility)null);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean canPlay() {
|
||||||
|
final Card land = this.getHostCard();
|
||||||
|
final Player p = this.getActivatingPlayer();
|
||||||
|
final Game game = p.getGame();
|
||||||
|
if (!p.canCastSorcery()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CantBeCast static abilities
|
||||||
|
for (final Card ca : game.getCardsIn(ZoneType.listValueOf("Battlefield,Command"))) {
|
||||||
|
final Iterable<StaticAbility> staticAbilities = ca.getStaticAbilities();
|
||||||
|
for (final StaticAbility stAb : staticAbilities) {
|
||||||
|
if (stAb.applyAbility("CantPlayLand", land, this)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (land != null) {
|
||||||
|
final boolean mayPlay = getMayPlay() != null;
|
||||||
|
if (land.getOwner() != p && !mayPlay) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Zone zone = game.getZoneOf(land);
|
||||||
|
if (zone != null && (zone.is(ZoneType.Battlefield) || (!zone.is(ZoneType.Hand) && !mayPlay))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// **** Check for land play limit per turn ****
|
||||||
|
// Dev Mode
|
||||||
|
if (p.getController().canPlayUnlimitedLands() || p.hasKeyword("You may play any number of additional lands on each of your turns.")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for adjusted max lands play per turn
|
||||||
|
int adjMax = 1;
|
||||||
|
for (String keyword : p.getKeywords()) {
|
||||||
|
if (keyword.startsWith("AdjustLandPlays")) {
|
||||||
|
final String[] k = keyword.split(":");
|
||||||
|
adjMax += Integer.valueOf(k[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p.getLandsPlayedThisTurn() < adjMax) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void resolve() {
|
||||||
|
getActivatingPlayer().playLandNoCheck(getHostCard());
|
||||||
|
|
||||||
|
// increase mayplay used
|
||||||
|
if (getMayPlay() != null) {
|
||||||
|
getMayPlay().incMayPlayTurn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toUnsuppressedString() {
|
||||||
|
StringBuilder sb = new StringBuilder("Play land");
|
||||||
|
StaticAbility sta = getMayPlay();
|
||||||
|
if (sta != null) {
|
||||||
|
Card source = sta.getHostCard();
|
||||||
|
if (!source.equals(getHostCard())) {
|
||||||
|
sb.append(" by ");
|
||||||
|
if ((source.isEmblem() || source.getType().hasSubtype("Effect"))
|
||||||
|
&& source.getEffectSource() != null) {
|
||||||
|
sb.append(source.getEffectSource());
|
||||||
|
} else {
|
||||||
|
sb.append(source);
|
||||||
|
}
|
||||||
|
if (sta.hasParam("MayPlayText")) {
|
||||||
|
sb.append(" (").append(sta.getParam("MayPlayText")).append(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -70,7 +70,7 @@ public class SpellAbilityPickerTest extends SimulationTestCase {
|
|||||||
|
|
||||||
SpellAbilityPicker picker = new SpellAbilityPicker(game, p);
|
SpellAbilityPicker picker = new SpellAbilityPicker(game, p);
|
||||||
SpellAbility sa = picker.chooseSpellAbilityToPlay(null);
|
SpellAbility sa = picker.chooseSpellAbilityToPlay(null);
|
||||||
assertEquals(game.PLAY_LAND_SURROGATE, sa);
|
//assertEquals(game.PLAY_LAND_SURROGATE, sa);
|
||||||
assertEquals(mountain, sa.getHostCard());
|
assertEquals(mountain, sa.getHostCard());
|
||||||
|
|
||||||
Plan plan = picker.getPlan();
|
Plan plan = picker.getPlan();
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import java.util.List;
|
|||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
import forge.game.spellability.LandAbility;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.player.GamePlayerUtil;
|
import forge.player.GamePlayerUtil;
|
||||||
@@ -162,7 +163,7 @@ public class InputPassPriority extends InputSyncronizedBase {
|
|||||||
if (sa.isSpell()) {
|
if (sa.isSpell()) {
|
||||||
return "cast spell";
|
return "cast spell";
|
||||||
}
|
}
|
||||||
if (sa == card.getGame().PLAY_LAND_SURROGATE) {
|
if (sa instanceof LandAbility) {
|
||||||
return "play land";
|
return "play land";
|
||||||
}
|
}
|
||||||
return "activate ability";
|
return "activate ability";
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import forge.game.cost.*;
|
import forge.game.cost.*;
|
||||||
|
import forge.game.spellability.LandAbility;
|
||||||
import forge.game.spellability.OptionalCostValue;
|
import forge.game.spellability.OptionalCostValue;
|
||||||
import forge.game.spellability.Spell;
|
import forge.game.spellability.Spell;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
@@ -66,8 +67,11 @@ public class HumanPlay {
|
|||||||
public final static boolean playSpellAbility(final PlayerControllerHuman controller, final Player p, SpellAbility sa) {
|
public final static boolean playSpellAbility(final PlayerControllerHuman controller, final Player p, SpellAbility sa) {
|
||||||
FThreads.assertExecutedByEdt(false);
|
FThreads.assertExecutedByEdt(false);
|
||||||
|
|
||||||
if (sa == controller.getGame().PLAY_LAND_SURROGATE) {
|
if (sa instanceof LandAbility) {
|
||||||
p.playLand(sa.getHostCard(), false);
|
sa.setActivatingPlayer(p);
|
||||||
|
if (sa.canPlay()) {
|
||||||
|
sa.resolve();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user