diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index e0d0525bccb..c3fba20e5a5 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -63,7 +63,6 @@ import java.io.File; import java.util.*; import java.util.concurrent.*; - /** * * @author nantuko @@ -85,7 +84,6 @@ public class ComputerPlayer6 extends ComputerPlayer implements private List suggested = new ArrayList(); protected Set actionCache; private static final List optimizers = new ArrayList(); - protected int lastLoggedTurn = 0; static { @@ -327,7 +325,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements } protected int minimaxAB(SimulationNode2 node, int depth, int alpha, int beta) { - logger.trace("Sim minimaxAB ["+depth+"] -- a: " + alpha + " b: " + beta + " <" + (node != null ? node.getScore() : "null")+">"); + logger.trace("Sim minimaxAB [" + depth + "] -- a: " + alpha + " b: " + beta + " <" + (node != null ? node.getScore() : "null") + ">"); UUID currentPlayerId = node.getGame().getPlayerList().get(); SimulationNode2 bestChild = null; for (SimulationNode2 child : node.getChildren()) { @@ -424,12 +422,11 @@ public class ComputerPlayer6 extends ComputerPlayer implements /** * Base call for simulation of AI actions - * + * * @return */ protected Integer addActionsTimed() { FutureTask task = new FutureTask(new Callable() { - @Override public Integer call() throws Exception { return addActions(root, maxDepth, Integer.MIN_VALUE, Integer.MAX_VALUE); @@ -457,8 +454,8 @@ public class ComputerPlayer6 extends ComputerPlayer implements } protected int addActions(SimulationNode2 node, int depth, int alpha, int beta) { - if (logger.isInfoEnabled() && node !=null && node.getAbilities() != null && !node.getAbilities().toString().equals("[Pass]")){ - logger.info("Add actions [" + depth +"] " + (node.getAbilities().toString()+ " -- a: " + alpha + " b: " + beta)); + if (logger.isInfoEnabled() && node != null && node.getAbilities() != null && !node.getAbilities().toString().equals("[Pass]")) { + logger.info("Add actions [" + depth + "] " + (node.getAbilities().toString() + " -- a: " + alpha + " b: " + beta)); } Game game = node.getGame(); int val; @@ -546,23 +543,23 @@ public class ComputerPlayer6 extends ComputerPlayer implements sim.checkStateAndTriggered(); int val = addActions(newNode, depth - 1, alpha, beta); - + if (logger.isInfoEnabled() && depth == maxDepth) { StringBuilder sb = new StringBuilder("Sim Prio [").append(depth).append("] #").append(counter) .append(" <").append(val).append("> (").append(action) - .append(action.isModal() ? " Mode = "+action.getModes().getMode().toString():"") + .append(action.isModal() ? " Mode = " + action.getModes().getMode().toString() : "") .append(listTargets(game, action.getTargets())).append(")") - .append(logger.isTraceEnabled()?" #" +newNode.hashCode():""); + .append(logger.isTraceEnabled() ? " #" + newNode.hashCode() : ""); SimulationNode2 logNode = newNode; - while (logNode.getChildren() != null && logNode.getChildren().size()>0) { + while (logNode.getChildren() != null && logNode.getChildren().size() > 0) { logNode = logNode.getChildren().get(0); - if (logNode.getAbilities() != null && logNode.getAbilities().size()>0) { + if (logNode.getAbilities() != null && logNode.getAbilities().size() > 0) { sb.append(" -> [").append(logNode.getDepth()).append("]").append(logNode.getAbilities().toString()).append("<").append(logNode.getScore()).append(">"); } } logger.info(sb); } - + if (currentPlayer.getId().equals(playerId)) { if (val > alpha) { alpha = val; @@ -622,7 +619,7 @@ public class ComputerPlayer6 extends ComputerPlayer implements node.children.clear(); node.children.add(bestNode); node.setScore(bestNode.getScore()); - if (logger.isTraceEnabled() && !bestNode.getAbilities().toString().equals("[Pass]") ) { + if (logger.isTraceEnabled() && !bestNode.getAbilities().toString().equals("[Pass]")) { logger.trace(new StringBuilder("Sim Prio [").append(depth).append("] -- Set after (depth=").append(depth).append(") <").append(bestNode.getScore()).append("> ").append(bestNode.getAbilities().toString()).toString()); } } @@ -656,7 +653,6 @@ public class ComputerPlayer6 extends ComputerPlayer implements optimizer.optimize(game, allActions); } Collections.sort(allActions, new Comparator() { - @Override public int compare(Ability ability, Ability ability1) { String rule = ability.toString(); @@ -1105,7 +1101,6 @@ public class ComputerPlayer6 extends ComputerPlayer implements && attacker.getToughness().getValue() <= blocker.getPower().getValue()) { safeToAttack = false; } - if (attacker.getToughness().getValue() == blocker.getPower().getValue() && attacker.getPower().getValue() == blocker.getToughness().getValue()) { if (attackerValue > blockerValue @@ -1120,13 +1115,18 @@ public class ComputerPlayer6 extends ComputerPlayer implements safeToAttack = false; } } - } - if (attacker.getAbilities().containsKey(DeathtouchAbility.getInstance().getId()) - || attacker.getAbilities().contains(new IndestructibleAbility())) { - safeToAttack = true; - } - if (attacker.getPower().getValue() == 0) { - safeToAttack = false; + if (attacker.getAbilities().containsKey(DeathtouchAbility.getInstance().getId()) + || attacker.getAbilities().contains(new IndestructibleAbility())) { + safeToAttack = true; + } + if (attacker.getAbilities().containsKey(FlyingAbility.getInstance().getId()) + && !blocker.getAbilities().containsKey(FlyingAbility.getInstance().getId()) + && !blocker.getAbilities().containsKey(ReachAbility.getInstance().getId())) { + safeToAttack = true; + } + if (attacker.getPower().getValue() == 0) { + safeToAttack = false; + } } if (safeToAttack) { attackingPlayer.declareAttacker(attacker.getId(), defenderId, game); @@ -1361,14 +1361,13 @@ public class ComputerPlayer6 extends ComputerPlayer implements protected String listTargets(Game game, Targets targets) { StringBuilder sb = new StringBuilder(); if (targets != null) { - for (Target target: targets) { + for (Target target : targets) { sb.append("[").append(target.getTargetedName(game)).append("]"); } - if (sb.length()>0) { - sb.insert(0," targeting "); + if (sb.length() > 0) { + sb.insert(0, " targeting "); } } return sb.toString(); } - } diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/SavagebornHydra.java b/Mage.Sets/src/mage/sets/dragonsmaze/SavagebornHydra.java new file mode 100644 index 00000000000..73335407b6e --- /dev/null +++ b/Mage.Sets/src/mage/sets/dragonsmaze/SavagebornHydra.java @@ -0,0 +1,114 @@ +/* + * 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.sets.dragonsmaze; + +import java.util.UUID; +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.Constants.Zone; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.ActivateAsSorceryActivatedAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.keyword.DoubleStrikeAbility; +import mage.cards.CardImpl; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author jeffwadsworth + */ +public class SavagebornHydra extends CardImpl { + + public SavagebornHydra(UUID ownerId) { + super(ownerId, 100, "Savageborn Hydra", Rarity.MYTHIC, new CardType[]{CardType.CREATURE}, "{X}{R}{G}"); + this.expansionSetCode = "DGM"; + this.subtype.add("Hydra"); + + this.color.setRed(true); + this.color.setGreen(true); + this.power = new MageInt(0); + this.toughness = new MageInt(0); + + // Double strike + this.addAbility(DoubleStrikeAbility.getInstance()); + + // Savageborn Hydra enters the battlefield with X +1/+1 counters on it. + this.addAbility(new EntersBattlefieldAbility(new SavageBornHydraEffect(), true)); + + // {1}{RG}: Put a +1/+1 counter on Savageborn Hydra. Activate this ability only any time you could cast a sorcery. + this.addAbility(new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.P1P1.createInstance()), new ManaCostsImpl("{1}{R/G}"))); + } + + public SavagebornHydra(final SavagebornHydra card) { + super(card); + } + + @Override + public SavagebornHydra copy() { + return new SavagebornHydra(this); + } +} + +class SavageBornHydraEffect extends OneShotEffect { + + public SavageBornHydraEffect() { + super(Constants.Outcome.BoostCreature); + } + + public SavageBornHydraEffect(final SavageBornHydraEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + Object obj = getValue(mage.abilities.effects.EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (obj != null && obj instanceof SpellAbility) { + int amount = ((SpellAbility)obj).getManaCostsToPay().getX(); + if (amount > 0) { + permanent.addCounters(CounterType.P1P1.createInstance(amount), game); + } + } + } + return true; + } + + @Override + public SavageBornHydraEffect copy() { + return new SavageBornHydraEffect(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/SpeciesGorger.java b/Mage.Sets/src/mage/sets/dragonsmaze/SpeciesGorger.java new file mode 100644 index 00000000000..0f42bb315d9 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dragonsmaze/SpeciesGorger.java @@ -0,0 +1,108 @@ +/* + * 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.sets.dragonsmaze; + +import java.util.UUID; +import mage.Constants; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.Constants.TargetController; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author jeffwadsworth + */ +public class SpeciesGorger extends CardImpl { + + public SpeciesGorger(UUID ownerId) { + super(ownerId, 105, "Species Gorger", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{G}{U}"); + this.expansionSetCode = "DGM"; + this.subtype.add("Frog"); + this.subtype.add("Beast"); + + this.color.setBlue(true); + this.color.setGreen(true); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // At the beginning of your upkeep, return a creature you control to its owner's hand. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Constants.Zone.BATTLEFIELD, new ReturnToHandChooseEffect(), TargetController.YOU, false)); + + } + + public SpeciesGorger(final SpeciesGorger card) { + super(card); + } + + @Override + public SpeciesGorger copy() { + return new SpeciesGorger(this); + } +} + +class ReturnToHandChooseEffect extends OneShotEffect { + + public ReturnToHandChooseEffect() { + super(Constants.Outcome.ReturnToHand); + this.staticText = "return a creature you control to its owner's hand"; + } + + public ReturnToHandChooseEffect(final ReturnToHandChooseEffect effect) { + super(effect); + } + + @Override + public ReturnToHandChooseEffect copy() { + return new ReturnToHandChooseEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(); + if (player.choose(this.outcome, target, source.getSourceId(), game)) { + Permanent permanent = game.getPermanent(target.getFirstTarget()); + if (permanent != null) { + return permanent.moveToZone(Constants.Zone.HAND, source.getId(), game, false); + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/SpikeJester.java b/Mage.Sets/src/mage/sets/dragonsmaze/SpikeJester.java new file mode 100644 index 00000000000..7826f054007 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dragonsmaze/SpikeJester.java @@ -0,0 +1,66 @@ +/* + * 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.sets.dragonsmaze; + +import java.util.UUID; +import mage.Constants.CardType; +import mage.Constants.Rarity; +import mage.MageInt; +import mage.abilities.keyword.HasteAbility; +import mage.cards.CardImpl; + +/** + * + * @author jeffwadsworth + */ +public class SpikeJester extends CardImpl { + + public SpikeJester(UUID ownerId) { + super(ownerId, 106, "Spike Jester", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{B}{R}"); + this.expansionSetCode = "DGM"; + this.subtype.add("Goblin"); + this.subtype.add("Warrior"); + + this.color.setRed(true); + this.color.setBlack(true); + this.power = new MageInt(3); + this.toughness = new MageInt(1); + + // Haste + this.addAbility(HasteAbility.getInstance()); + } + + public SpikeJester(final SpikeJester card) { + super(card); + } + + @Override + public SpikeJester copy() { + return new SpikeJester(this); + } +} diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/TajicBladeOfTheLegion.java b/Mage.Sets/src/mage/sets/dragonsmaze/TajicBladeOfTheLegion.java new file mode 100644 index 00000000000..d72f99b5489 --- /dev/null +++ b/Mage.Sets/src/mage/sets/dragonsmaze/TajicBladeOfTheLegion.java @@ -0,0 +1,74 @@ +/* + * 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.sets.dragonsmaze; + +import java.util.UUID; +import mage.Constants.CardType; +import mage.Constants.Duration; +import mage.Constants.Rarity; +import mage.MageInt; +import mage.abilities.effects.common.continious.BoostSourceEffect; +import mage.abilities.keyword.BattalionAbility; +import mage.abilities.keyword.IndestructibleAbility; +import mage.cards.CardImpl; + +/** + * + * @author jeffwadsworth + */ +public class TajicBladeOfTheLegion extends CardImpl { + + public TajicBladeOfTheLegion(UUID ownerId) { + super(ownerId, 107, "Tajic, Blade of the Legion", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{2}{R}{W}"); + this.expansionSetCode = "DGM"; + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Soldier"); + + this.color.setRed(true); + this.color.setWhite(true); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Tajic, Blade of the Legion is indestructible. + this.addAbility(new IndestructibleAbility()); + + // Battalion - Whenever Tajic and at least two other creatures attack, Tajic gets +5/+5 until end of turn. + this.addAbility(new BattalionAbility(new BoostSourceEffect(5, 5, Duration.EndOfTurn))); + + } + + public TajicBladeOfTheLegion(final TajicBladeOfTheLegion card) { + super(card); + } + + @Override + public TajicBladeOfTheLegion copy() { + return new TajicBladeOfTheLegion(this); + } +}