mirror of
https://github.com/magefree/mage.git
synced 2026-01-10 21:02:08 -08:00
Some fixes/improvements to AI target handling and tests.
This commit is contained in:
parent
7ce030101c
commit
0c0fe9984e
7 changed files with 217 additions and 92 deletions
|
|
@ -302,10 +302,10 @@ public class SimulatedPlayer2 extends ComputerPlayer {
|
|||
}
|
||||
|
||||
if (bad) {
|
||||
// remove its own creatures, player itself for bad effects
|
||||
// remove its own creatures, player itself for bad effects with one target
|
||||
while (iterator.hasNext()) {
|
||||
Ability ability1 = iterator.next();
|
||||
if (ability1.getTargets().size() == 1) {
|
||||
if (ability1.getTargets().size() == 1 && ability1.getTargets().get(0).getTargets().size() == 1) {
|
||||
Permanent permanent = game.getPermanent(ability1.getFirstTarget());
|
||||
if (permanent != null && !game.getOpponents(playerId).contains(permanent.getControllerId())) {
|
||||
iterator.remove();
|
||||
|
|
@ -318,10 +318,10 @@ public class SimulatedPlayer2 extends ComputerPlayer {
|
|||
}
|
||||
}
|
||||
if (good) {
|
||||
// remove opponent creatures and opponent for only good effects
|
||||
// remove opponent creatures and opponent for only good effects with one target
|
||||
while (iterator.hasNext()) {
|
||||
Ability ability1 = iterator.next();
|
||||
if (ability1.getTargets().size() == 1) {
|
||||
if (ability1.getTargets().size() == 1 && ability1.getTargets().get(0).getTargets().size() == 1) {
|
||||
Permanent permanent = game.getPermanent(ability1.getFirstTarget());
|
||||
if (permanent != null && game.getOpponents(playerId).contains(permanent.getControllerId())) {
|
||||
iterator.remove();
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
private transient final static Logger log = Logger.getLogger(ComputerPlayer.class);
|
||||
|
||||
protected int PASSIVITY_PENALTY = 5; // Penalty value for doing nothing if some actions are availble
|
||||
protected boolean ALLOW_INTERRUPT = true; // change this for test purposes to switch off interrupts while debugging
|
||||
protected boolean ALLOW_INTERRUPT = false; // change this for test / debugging purposes to false to switch off interrupts while debugging
|
||||
|
||||
private transient Map<Mana, Card> unplayable = new TreeMap<>();
|
||||
private transient List<Card> playableNonInstant = new ArrayList<>();
|
||||
|
|
@ -301,12 +301,25 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
}
|
||||
for (Permanent permanent : targets) {
|
||||
if (((TargetPermanent) target).canTarget(abilityControllerId, permanent.getId(), null, game) && !target.getTargets().contains(permanent.getId())) {
|
||||
// stop to add targets if not needed and outcome is no advantage for AI player
|
||||
if (target.getNumberOfTargets() == target.getTargets().size()) {
|
||||
if (outcome.isGood() && hasOpponent(permanent.getControllerId(), game)) {
|
||||
return true;
|
||||
}
|
||||
if (!outcome.isGood() && !hasOpponent(permanent.getControllerId(), game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// add the target
|
||||
target.add(permanent.getId(), game);
|
||||
return true;
|
||||
if (target.doneChosing()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return target.isChosen();
|
||||
}
|
||||
|
||||
if (target instanceof TargetCardInHand) {
|
||||
List<Card> cards = new ArrayList<>();
|
||||
for (UUID cardId : ((TargetCardInHand) target).possibleTargets(sourceId, this.getId(), game)) {
|
||||
|
|
|
|||
|
|
@ -49,12 +49,12 @@ import mage.target.TargetPermanent;
|
|||
* @author JotaPeRL
|
||||
*/
|
||||
public class NovijenSages extends CardImpl {
|
||||
|
||||
|
||||
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creatures you control with a +1/+1 counter on it");
|
||||
|
||||
static {
|
||||
filter.add(new CounterPredicate(CounterType.P1P1));
|
||||
}
|
||||
}
|
||||
|
||||
public NovijenSages(UUID ownerId) {
|
||||
super(ownerId, 27, "Novijen Sages", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{4}{U}{U}");
|
||||
|
|
@ -67,10 +67,10 @@ public class NovijenSages extends CardImpl {
|
|||
|
||||
// Graft 4
|
||||
this.addAbility(new GraftAbility(this, 4));
|
||||
|
||||
|
||||
// {1}, Remove two +1/+1 counters from among creatures you control: Draw a card.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), new GenericManaCost(1));
|
||||
ability.addCost(new RemoveCounterCost(new TargetPermanent(1, Integer.MAX_VALUE, filter, true), CounterType.P1P1, 2));
|
||||
ability.addCost(new RemoveCounterCost(new TargetPermanent(1, 2, filter, true), CounterType.P1P1, 2));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package org.mage.test.AI.basic;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBaseAI;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class TargetsAreChosenTest extends CardTestPlayerBaseAI {
|
||||
|
||||
/**
|
||||
* Check that the AI selects a target from the own artifacts and also an
|
||||
* artifact from the opponent artficats
|
||||
*/
|
||||
@Test
|
||||
public void testRackAndRuin() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
// Destroy two target artifacts.
|
||||
addCard(Zone.HAND, playerA, "Rack and Ruin"); // {2}{R}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mox Emerald", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Juggernaut");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Rack and Ruin", 1);
|
||||
assertGraveyardCount(playerA, "Mox Emerald", 1);
|
||||
assertGraveyardCount(playerB, "Juggernaut", 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the AI does not cast Rack and Ruin if it would destroy the
|
||||
* owly creature on the battlefield owned by the AI
|
||||
*/
|
||||
@Test
|
||||
public void testRackAndRuin2() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
// Destroy two target artifacts.
|
||||
addCard(Zone.HAND, playerA, "Rack and Ruin"); // {2}{R}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mox Emerald");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Juggernaut");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Rack and Ruin", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the AI does cast Rack and Ruin if it would destroy two targets
|
||||
* of the opponent
|
||||
*/
|
||||
@Test
|
||||
public void testRackAndRuin3() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
// Destroy two target artifacts.
|
||||
addCard(Zone.HAND, playerA, "Rack and Ruin"); // {2}{R}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mox Emerald", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Juggernaut");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Rack and Ruin", 1);
|
||||
assertGraveyardCount(playerB, "Mox Emerald", 2);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,30 +14,33 @@ public class BoseijuTest extends CardTestPlayerBase {
|
|||
* Boseiju, Who Shelters All
|
||||
* Legendary Land
|
||||
* Boseiju, Who Shelters All enters the battlefield tapped.
|
||||
* {T}, Pay 2 life: Add {1} to your mana pool. If that mana is spent on an
|
||||
* {T}, Pay 2 life: Add {1} to your mana pool. If that mana is spent on an
|
||||
* instant or sorcery spell, that spell can't be countered by spells or abilities.
|
||||
*
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
// test that instants and soceries can't be countered when Boseiju mana is used
|
||||
@Test
|
||||
public void testCantCounter() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Boseiju, Who Shelters All");
|
||||
addCard(Zone.HAND, playerA, "Brilliant Plan");
|
||||
addCard(Zone.HAND, playerA, "Counterspell");
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Island", 2);
|
||||
// Draw three cards.
|
||||
addCard(Zone.HAND, playerA, "Brilliant Plan"); // {4}{U}
|
||||
|
||||
addCard(Zone.HAND, playerB, "Counterspell"); // {U}{U}
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brilliant Plan");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Counterspell", "Brilliant Plan");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Counterspell", "Brilliant Plan");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
|
||||
this.assertHandCount(playerA, 3);
|
||||
this.assertGraveyardCount(playerA, "Counterspell", 1);
|
||||
|
||||
this.assertGraveyardCount(playerB, "Counterspell", 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// test that instants and soceries can be countered when Boseiju mana is not used
|
||||
@Test
|
||||
public void testCanCounter() {
|
||||
|
|
@ -45,16 +48,16 @@ public class BoseijuTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Boseiju, Who Shelters All");
|
||||
addCard(Zone.HAND, playerA, "Mental Note");
|
||||
addCard(Zone.HAND, playerA, "Counterspell");
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mental Note");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Counterspell", "Mental Note");
|
||||
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
|
||||
this.assertHandCount(playerA, 0);
|
||||
this.assertGraveyardCount(playerA, 2);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
|
|
@ -20,16 +20,14 @@
|
|||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.costs.common;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
|
|
@ -55,7 +53,7 @@ public class RemoveCounterCost extends CostImpl {
|
|||
private String name;
|
||||
private CounterType counterTypeToRemove;
|
||||
private int countersToRemove;
|
||||
|
||||
|
||||
public RemoveCounterCost(TargetPermanent target) {
|
||||
this(target, null);
|
||||
}
|
||||
|
|
@ -88,7 +86,7 @@ public class RemoveCounterCost extends CostImpl {
|
|||
if (controller != null) {
|
||||
target.clearChosen();
|
||||
if (target.choose(Outcome.UnboostCreature, controllerId, sourceId, game)) {
|
||||
for (UUID targetId: (List<UUID>)target.getTargets()) {
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
Permanent permanent = game.getPermanent(targetId);
|
||||
if (permanent != null) {
|
||||
if (permanent.getCounters().size() > 0 && (counterTypeToRemove == null || permanent.getCounters().containsKey(counterTypeToRemove))) {
|
||||
|
|
@ -123,18 +121,19 @@ public class RemoveCounterCost extends CostImpl {
|
|||
int numberOfCountersSelected = 1;
|
||||
if (countersLeft > 1 && countersOnPermanent > 1) {
|
||||
numberOfCountersSelected = controller.getAmount(1, Math.min(countersLeft, countersOnPermanent),
|
||||
new StringBuilder("Remove how many counters from ").append(permanent.getIdName()).toString(), game);
|
||||
new StringBuilder("Remove how many counters from ").append(permanent.getIdName()).toString(), game);
|
||||
}
|
||||
permanent.removeCounters(counterName, numberOfCountersSelected, game);
|
||||
if (permanent.getCounters().getCount(counterName) == 0 ){
|
||||
if (permanent.getCounters().getCount(counterName) == 0) {
|
||||
permanent.getCounters().removeCounter(counterName);
|
||||
}
|
||||
countersRemoved += numberOfCountersSelected;
|
||||
if (!game.isSimulation())
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers(new StringBuilder(controller.getLogName())
|
||||
.append(" removes ").append(numberOfCountersSelected == 1 ? "a":numberOfCountersSelected).append(" ")
|
||||
.append(counterName).append(numberOfCountersSelected == 1 ? " counter from ":" counters from ")
|
||||
.append(permanent.getName()).toString());
|
||||
.append(" removes ").append(numberOfCountersSelected == 1 ? "a" : numberOfCountersSelected).append(" ")
|
||||
.append(counterName).append(numberOfCountersSelected == 1 ? " counter from " : " counters from ")
|
||||
.append(permanent.getName()).toString());
|
||||
}
|
||||
if (countersRemoved == countersToRemove) {
|
||||
this.paid = true;
|
||||
break;
|
||||
|
|
@ -160,7 +159,7 @@ public class RemoveCounterCost extends CostImpl {
|
|||
if (counterTypeToRemove != null) {
|
||||
sb.append(counterTypeToRemove.getName());
|
||||
}
|
||||
sb.append(countersToRemove == 1 ? " counter from ":" counters from ").append(target.getMaxNumberOfTargets() == 1 ? "a ":"").append(target.getTargetName());
|
||||
sb.append(countersToRemove == 1 ? " counter from " : " counters from ").append(target.getMaxNumberOfTargets() == 1 ? "a " : "").append(target.getTargetName());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,46 +1,53 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package mage.target;
|
||||
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.*;
|
||||
import mage.MageObject;
|
||||
import mage.constants.AbilityType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
|
@ -104,7 +111,7 @@ public abstract class TargetImpl implements Target {
|
|||
public void setMinNumberOfTargets(int minNumberOftargets) {
|
||||
this.minNumberOfTargets = minNumberOftargets;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setMaxNumberOfTargets(int maxNumberOftargets) {
|
||||
this.maxNumberOfTargets = maxNumberOftargets;
|
||||
|
|
@ -116,7 +123,7 @@ public abstract class TargetImpl implements Target {
|
|||
if (targetController != null) {
|
||||
// Hint for the selecting player that the targets must be valid from the point of the ability controller
|
||||
// e.g. select opponent text may be misleading otherwise
|
||||
suffix = " (target controlling!)";
|
||||
suffix = " (target controlling!)";
|
||||
}
|
||||
if (getMaxNumberOfTargets() != 1) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
|
@ -158,7 +165,7 @@ public abstract class TargetImpl implements Target {
|
|||
public Zone getZone() {
|
||||
return zone;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRequired(UUID sourceId, Game game) {
|
||||
MageObject object = game.getObject(sourceId);
|
||||
|
|
@ -168,12 +175,12 @@ public abstract class TargetImpl implements Target {
|
|||
return isRequired();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isRequired(Ability ability) {
|
||||
return ability == null || ability.isActivated() || !(ability.getAbilityType().equals(AbilityType.SPELL) || ability.getAbilityType().equals(AbilityType.ACTIVATED));
|
||||
|
|
@ -217,6 +224,7 @@ public abstract class TargetImpl implements Target {
|
|||
if (!targets.containsKey(id)) {
|
||||
targets.put(id, 0);
|
||||
rememberZoneChangeCounter(id, game);
|
||||
chosen = targets.size() >= getNumberOfTargets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -254,7 +262,7 @@ public abstract class TargetImpl implements Target {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateTarget(UUID id, Game game) {
|
||||
rememberZoneChangeCounter(id, game);
|
||||
|
|
@ -315,7 +323,7 @@ public abstract class TargetImpl implements Target {
|
|||
int i = 0;
|
||||
int rnd = new Random().nextInt(possibleTargets.size());
|
||||
Iterator it = possibleTargets.iterator();
|
||||
while( i < rnd) {
|
||||
while (i < rnd) {
|
||||
it.next();
|
||||
i++;
|
||||
}
|
||||
|
|
@ -336,9 +344,9 @@ public abstract class TargetImpl implements Target {
|
|||
@Override
|
||||
public boolean isLegal(Ability source, Game game) {
|
||||
//20101001 - 608.2b
|
||||
Set <UUID> illegalTargets = new HashSet<>();
|
||||
Set<UUID> illegalTargets = new HashSet<>();
|
||||
// int replacedTargets = 0;
|
||||
for (UUID targetId: targets.keySet()) {
|
||||
for (UUID targetId : targets.keySet()) {
|
||||
Card card = game.getCard(targetId);
|
||||
if (card != null) {
|
||||
if (zoneChangeCounters.containsKey(targetId) && zoneChangeCounters.get(targetId) != card.getZoneChangeCounter(game)) {
|
||||
|
|
@ -356,7 +364,7 @@ public abstract class TargetImpl implements Target {
|
|||
}
|
||||
}
|
||||
// remove illegal targets, needed to handle if only a subset of targets was illegal
|
||||
for (UUID targetId: illegalTargets) {
|
||||
for (UUID targetId : illegalTargets) {
|
||||
targets.remove(targetId);
|
||||
}
|
||||
// if (replacedTargets > 0 && replacedTargets == targets.size()) {
|
||||
|
|
@ -381,7 +389,7 @@ public abstract class TargetImpl implements Target {
|
|||
target.addTarget(targetId, source, game, true);
|
||||
if (!target.isChosen()) {
|
||||
Iterator<UUID> it2 = possibleTargets.iterator();
|
||||
while (it2.hasNext()&& !target.isChosen()) {
|
||||
while (it2.hasNext() && !target.isChosen()) {
|
||||
UUID nextTargetId = it2.next();
|
||||
target.addTarget(nextTargetId, source, game, true);
|
||||
}
|
||||
|
|
@ -389,7 +397,7 @@ public abstract class TargetImpl implements Target {
|
|||
if (target.isChosen()) {
|
||||
options.add(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
|
|
@ -458,6 +466,6 @@ public abstract class TargetImpl implements Target {
|
|||
} else {
|
||||
return game.getPlayer(playerId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue